ときどきの雑記帖 RE* (新南口)
生存戦略
総総
Eテレの2355で 「総総」は何と読むかと言う問題(?)が出たのだけど 答えを見てびっくり。
「総総」の読み方知ってる?正解見たら想像を遥かに超えてきた……。【読み間違いが多い漢字】 | antenna[アンテナ]
代行収納
コンビニ店員がレジでパニックになる客の言動。“モチジュウ”って何?――コンビニの困った客トップ5 | 日刊SPA!
最近は税金関係や電気・ガス・水道料金などの代行収納が多い。間違えたら客から苦情がくる。心が折れそうになるが、 そこは仕事、しっかりやらないといけない。
では、何が嫌なのかと言えば、あらかじめ請求書の部分を切り離しておらず、紙ぜんぶをそのまま渡してくる客が意外と多いのだ。 スタッフとしては手間が増える。
の「請求書の部分を切り離す」のところ、 具体的にどの部分を指しているのかわからんけど あれ(払込票のミシン目部分)って払い込む側が勝手に切り離しちゃいけないものなのでは?
公共料金のコンビニ支払い方法とは? 手数料や期限切れの場合についても解説 | マイナビニュース
請求書には、客の控えの部分に切り離しができる点線がついています。ついうっかり自分で切り離してしまいがちですが、これはNG。 コンビニのレジで、支払いの終了後に店員が切り離すものなので注意しましょう。
振込用紙でのお支払い手続き|お支払い手続き|東京電力エナジーパートナー株式会社
銀行やコンビニエンス・ストアなどでお支払いの場合は、「電気料金等振込用紙」、「電気使用量のお知らせ(検針票)」、 「電気料金等請求書」を 切り離さないで、お支払い窓口へお持ちください。
ただちょっと検索してみたところ、 世の中には払込票にくっついたお知らせや宛先が印刷された部分などもそのままでだすとか、 中には未開封の封筒ごとレジに出すという御仁もいるらしいので そういうことを言ってるのかもしれない。
アニメ東京ステーション
日本アニメの発信拠点「アニメ東京ステーション」がオープン | NHK | アニメ
トップの写真に電車の顔(?)や背中後頭部(?)が映っているけど、
ひょっとして以前丸善の文具専門店があった建物?
丸善池袋店、2021年7月31日閉店-電車がある「都内最大級の文具専門店」、僅か4年の歴史に幕 | 都市商業研究所
Dateとかstrptimeとか
date (GNU coreutils)
Linuxコマンドのワンライナーで連続した日付を生成したい #Linux - Qiita のコメントに
seq -f 2023/09/07+%gdays 0 14 | date -f - +%Y/%m/%d
とすると 一回のdateコマンドの起動で複数の結果を得ることができるということが書かれていて、 「そのオプション知らなかったわー」 から、いろいろ検索していたら次の記事を見つけた
date (BSD)
$ date -j -f '%Y%m%d' 20160200 2> /dev/null
2016年 1月31日 日曜日 21時48分31秒 JST
$ echo $?
0
(先の例と同じ -f
というオプション指定だけどGNUとBSDで別の意味なので注意)
要するに2016年2月0日(20160200)を正しい日付として受け付けてしまうというもので、
はじめはこれってmktime(3)
のように「気を利かせてくれた」んじゃないの?
と思ったのだけど、
GNU coreutilsのdateではエラーだということなので
ソースコードにあたってみた
(そこに至るまでのあれこれはさくっと省略)。
で、どうもこれはdateコマンドで使っている
strptime(3)
の動作の問題らしい。
MacOS付属のdateコマンドのソースはどこを見るのが良いのか わからないのだけど shell_cmds/date/date.c at main · apple-oss-distributions/shell_cmds · GitHub によれば-fオプションで書式文字列が与えられたときに 日付チェックを行っているのは
if (fmt != NULL) {
t = strptime(p, fmt, lt);
if (t == NULL) {
fprintf(stderr, "Failed conversion of ``%s''"
" using format ``%s''\n", p, fmt);
badformat();
} else if (*t != '\0')
fprintf(stderr, "Warning: Ignoring %ld extraneous"
" characters in date string (%s)\n",
(long) strlen(t), t);
} else {
というコードで、
このstrptime
が20160200
という入力を受け付けているように思われる。
元になった(?)FreeBSD版は(別個に手が入っている可能性はある)こちら freebsd-src/bin/date/date.c at main · freebsd/freebsd-src
if (fmt != NULL) {
t = strptime(p, fmt, lt);
if (t == NULL) {
fprintf(stderr, "Failed conversion of ``%s''"
" using format ``%s''\n", p, fmt);
badformat();
} else if (*t != '\0')
fprintf(stderr, "Warning: Ignoring %ld extraneous"
" characters in date string (%s)\n",
(long) strlen(t), t);
} else {
同じですね。
strptimeの仕様
それではとstrptime(3)
の仕様を確認してみると
%d
The day of the month [01,31]; leading zeros are permitted but not required.
The Open Group Base Specifications Issue 7, 2018 edition
d
The day of the month [01,31]; leading zeros shall be permitted but shall not be required.
一桁の日付は01
、02
のようにleading zerosを許容すべきだけど
それは必須ではない。と。
ただ、00
とか0
をどう扱うかについては書かれていない。
%d または %e
月内の日付 (1-31)。
%d is replaced by the day of the month as a decimal number (01-31).
All conversion specifications are identical to those described in strftime(3).
%d is replaced by the day of the month as a decimal number (01-31).
01
から31
とあるし00
はエラーになりそうなものだけど…
それではとstrptime
の実装
Libc/stdtime/FreeBSD/strptime.c at main · apple-oss-distributions/Libc - GitHub
のcase 'd':
辺りを見ると
(インデント量など変更しているので注意)
/*
* The %e specifier was once explicitly documented as
* not being zero-padded but was later changed to
* equivalent to %d. There is no harm in allowing
* such padding.
*
* XXX The %e specifier may gobble one too many
* digits if used incorrectly.
*/
/* Leading space is ok if date is single digit */
len = field_width ? field_width : 2;
if (isspace_l((unsigned char)buf[0], locale) &&
isdigit_l((unsigned char)buf[1], locale) &&
!isdigit_l((unsigned char)buf[2], locale)) {
len = 1;
buf++;
}
if (!isdigit_l((unsigned char)*buf, locale))
return (NULL);
for (i = 0; len && *buf != 0 &&
isdigit_l((unsigned char)*buf, locale); buf++) {
i *= 10;
i += *buf - '0';
len--;
}
if (i > 31)
return (NULL);
tm->tm_mday = i;
flags |= FLAG_MDAY;
break;
ん? このコードだとiが0の場合(20160200
のケースが該当する)もエラーにならないんじゃ?
で、FreeBSDでの https://github.com/freebsd/freebsd-src/blob/main/lib/libc/stdtime/strptime.c#L429 の同じ部分を見ると
if (i == 0 || i > 31)
return (NULL);
やはりさっきの部分はバグだったっぽい (いつ頃修正されたかは調べていない)。
Macの環境を持っていないのでそのまま使えるかはわからないけど、 こんなプログラムを書いてUbuntuで試してみた。
#define __USE_XOPEN
#define _XOPEN_SOURCE 650
#include <stdio.h>
#include <time.h>
int
main()
{
const char* dates[] = {
"20230131",
"20230200",
"20230201",
NULL,
};
for (const char **p=dates; *p; p++) {
struct tm t={0};
if (strptime(*p,"%Y%m%d", &t))
printf("%s -> success\n", *p);
else
printf("%s -> fail\n", *p);
}
return 0;
}
余談
Man page of STRPTIME の書式の部分に
#define _XOPEN_SOURCE /* feature_test_macros(7) 参照 */
#include <time.h>
char *strptime(const char *s, const char *format, struct tm *tm);
とあるように、glibc環境では
__USE_XOPEN
(と_XOPEN_SOURCE
)
を適切に定義しないとコンパイルもできないのだけど、
しばらくそれに気がつかず(忘れていて)悩んだのはここだけの話。
閑話休題。 Ubuntuでの実行結果はこう。
kbk@toybox4:~$ ./a.out
20230131 -> success
20230200 -> fail
20230201 -> success
当然(?)のようにエラーにしてますね。
余談その2
最初はmingwでやろうとしたのだけど、
mingwのライブラリにはstrptime(3)
がないらしく
それに気がつくまで時間を浪費してしまった。
python
strptimeでいろいろ検索していたらこんなのもみつかった。
本当は怖いstrptimeと%Y%m%dの関係 | Nekoya press
この記事にある結果を表にするとこんな感じ
処理系 | 201312 | 2013129 | 2013130 |
---|---|---|---|
Python 2.7.1 | 2013年1月2日 | 2013年12月9日 | 2013年1月30日 |
Perl5.12.2 | 2013年12月1日 | 2013年12月9日 | エラー |
PHP5.3.15 | 2013年6月10日 | 2013年5月9日 | 2013年5月10日 |
Ruby1.9.3p194 | エラー | 2013年12月9日 | エラー |
他は何となくなぜそうなったのか推測できる結果だけど、 PHPの結果はなんでこうなるのかよくわからんな…
なお10年前の記事なので現時点では各処理系の状況は変わっている可能性に注意。 たとえばPHPはこうなっていた
警告 この関数は PHP 8.1.0 で 非推奨になります。この関数に頼らないことを強く推奨します。
この関数は、推奨されなくなりました。 date_parse_from_format() (ロケールに依存しないパースを行う場合) または、 IntlDateFormatter::parse() (ロケールに依存するパースを行う場合) を使って下さい。
PHPについてはこんな話もあった模様 (同じ著者による記事で内容は変わらない)。
で、Python。
>python
Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import tzinfo, timedelta, datetime
>>> datetime.strptime('2013130', '%Y%m%d')
datetime.datetime(2013, 1, 30, 0, 0)
>>> datetime.strptime('2013120', '%Y%m%d')
datetime.datetime(2013, 1, 20, 0, 0)
>>> datetime.strptime('2013121', '%Y%m%d')
datetime.datetime(2013, 12, 1, 0, 0)
>>> datetime.strptime('201310', '%Y%m%d')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python310\lib\_strptime.py", line 568, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
File "C:\Python310\lib\_strptime.py", line 349, in _strptime
raise ValueError("time data %r does not match format %r" %
ValueError: time data '201310' does not match format '%Y%m%d'
>>> datetime.strptime('201311', '%Y%m%d')
datetime.datetime(2013, 1, 1, 0, 0)
バージョンが微妙に古いのはさておき、10年前と同じ動作のようだ。
最後の201310
がさすがにエラーになるのはまあそんなもんだろう。
この辺りの動作について何かドキュメントに明記されているかもと
datetime — 基本的な日付型および時間型 — Python 3.12.0 ドキュメント
を見てみたが見当たらなかった(見落としてたらすまん)
それはそれとして、スタックトレースに出てきたlib/_strptime.pyがひっかったので コードを見てみたらこんなんだった(ポイントとなる部分だけ)
class TimeRE(dict):
...
base.__init__({
# The " [1-9]" part of the regex is to make %c from ANSI C work
'd': r"(?P<d>3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])",
...
'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])",
あー。 確かに記事にあったような(そして自分で試したような) 動きになるわこれ。
でもこれって、「小さな親切(以下略)」の類のような?🤔
- datetime.datetime.strptime get day error · Issue #84417 · python/cpython · GitHub
- 課題 23136: BUG in how _strptime() handles week 0 - Python tracker
- TmStruct, strptime bug in wrong day of week · Issue #6913 · JuliaLang/julia · GitHub
- datetime - Strptime Error in Python - Stack Overflow
- Pythonのstrptime %zに関するバグ報告をした - プログラムモグモグ
awk
gawk
お、5.3.0がリリースされた
Changes from 5.2.x to 5.3.0
---------------------------
1. Infrastructure changes: Removed the use of libsigsegv. The
value-add was never very much and it caused problems in some
environments.
2. In keeping with new features in BWK awk, gawk now has built-in
CSV file parsing. The behavior is intended to be identical to
that of the "One True AWK" when --csv is applied. See the
manual for details.
3. Also in keeping with BWK awk, gawk now supports a new \u escape
sequence. This should be followed by 1-8 hexadecimal digits. The
given code point is converted to its corresponding multibyte encoding
for storage inside gawk. See the manual.
4. If PROCINFO["BUFFERPIPE"] exists, then pipe output is buffered.
You can also use PROCINFO["command", "BUFFERPIPE"]. See the manual
for details.
5. Because of the additional `do_csv' variable in the API, which breaks
binary compatibility, the API major version was updated to 4 and
the minor version was reset to zero. The API remains source code
compatible; that is, existing extensions should only require recompilation.
6. The manual now requires Texinfo 7.1 and its texinfo.tex for formatting.
As a result, we no longer need to pre-process it, removing the need
for gawktexi.in and leaving just gawk.texi.
7. And of course, there have been several minor code cleanups and bug fixes.
See the ChangeLog for details.
Changes from 5.2.2 to 5.2.x
---------------------------
1. The readdir extension has been updated with additonal code and
features, see the manual or its man page. As a result, the
readdir_test.c extension has been removed.
2. We have a new translation: Ukranian.
3. Several subtle issues related to null regexp matches around
multibyte characters have been fixed.
3と4がちょっと気になるけど(8桁までって?) 基本csv対応のためのリリースという感じすね。
unicode on Cygwin
Fix for unicode on Cygwin. gawk.git - gawk でこんなコードが追加されていた
--- a/posix/gawkmisc.c
+++ b/posix/gawkmisc.c
@@ -316,3 +316,22 @@ cygwin_premain2(int argc, char **argv, struct per_process *myself)
setmode(fileno (stdin), O_TEXT);
}
#endif
+
+#ifdef __CYGWIN__
+size_t
+wcitomb (char *s, int wc, mbstate_t *ps)
+{
+ /* If s is NULL, behave as if s pointed to an internal buffer and wc
+ was a null wide character (L''). wcrtomb will do that for us*/
+ if (wc <= 0xffff || !s)
+ return wcrtomb (s, (wchar_t) wc, ps);
+
+ wchar_t wc_arr[2];
+ const wchar_t *wcp = wc_arr;
+
+ wc -= 0x10000;
+ wc_arr[0] = (wc >> 10) + 0xd800;
+ wc_arr[1] = (wc & 0x3ff) + 0xdc00;
+ return wcsnrtombs (s, &wcp, 2, SIZE_MAX, ps);
+}
+#endif
0xd800とか0xdc00があるということはサロゲートペア絡みすか。
FORTRAN Compiler on IBM 704
STATE C、これまで見なかったテクニックがいくつか出てきて 面白いけど追いかける(動作を把握する)のがタイヘン。
新刊近刊
サピエンス全史
文庫が出てた。 後に出た本が文庫になってたのにこれはなってなかったりして かつてのハヤカワの「アルジャーノンに花束を」と同じパターンかと 思ってたけどついにというかようやくというか。
なんのかんので実はまだ読んでいないのだけど 文庫だと手を出しやすいかな。
道交法
今日イチびっくりしたドラレコ動画 pic.twitter.com/CFlOuauCH9
— てゃん。MMCHD🍃🫧 (@sankichi_ZYX10) November 2, 2023
実物大98式初登場の頃に聞いた話だったと思うけど、 実物大98式の腕を付けたままトレーラーに載せて 公道を走ることは道交法上できないのだそうだ (幅の問題だったかな?)。
つまりパトレイバー作中では 現実とは道交法が違うということに😄
武帝
日本の古代の暦では干支で年や日を表しているが、この干支というもの、中国の武帝が使い始めたと記録がある。これが紀元前104年で三統暦が施行されたとき
— なぎせ ゆうき (@nagise) November 3, 2023
中国史には「武帝」がたくさんいる (たとえば曹操(魏武)) ことについて。 まあ漢(前漢)の武帝を指しているんだろうけど。
進歩
雑談によってだいぶ問題意識が言語化された。ある技術Xによって人が行うタスクTの9割が消滅する可能性がある時に、人がタスクTをやる効率を1割上げることを「進歩」と捉えるかどうか、ということ
— nishio hirokazu (@nishio) November 3, 2023