還暦過ぎたエンジニアの挑戦

いくつになっても好奇心だけは忘れないエンジニア Hikaruのブログ

MENU

デートに潜む罠

ナイスな感じ デートに潜む罠
ナイスな感じだけど。。。
まあ、いくら青春しているとはいえ、この歳で語る話でもないですが。。。

って違います。

Dateのことです。 日付の話です。😓

日付は腐れ縁

デジタルの世界では日付とうまく付き合うことは今や当たり前のことですね。

  • 今日の売り上げ
  • 今月の予算
  • 明日の予定

などなど、
何かにつけて日付をキーにして何かすることは常識的な茶飯事で
どんなポジションのエンジニアも、誰しもが関わる話です。

でも日付の計算と簡単に言うけれど、

  • 毎月の日数が違う
  • 4年に一度はうるう年がある
  • 100年に一度はうるう年をうるう年ではなくするが400年ごとにやっぱうるう年にする(だから2000年はうるう年だった)

と、まあ扱いにくいことこの上無いです。😩

おまけに 1日は24時間、1時間は60分、1分は60秒

って誰が勝手に決めたんだ?
1日は10時間、1時間は100分、1分は100秒
だったらどれだけいろいろな計算が楽になっていたか。。。

経済効果も大分違っていたと思う。(ホントか?)🙄

タイムスタンプと付き合う

さて、本題

その時間の計算やデータとして記録するために
UNIXタイムスタンプというのを使います。
1970年1月1日の1:00から何秒経過しているかの数値で特定の時刻を表すものです。
(これも不思議な話の一つ ・・・なぜ0:00を基準にしなかったのかな??) 😏 例えば、タイムスタンプが 1612088566 なら 2021年1月31日の11:22:46 のことです。

これをphpではdate関数というものを使って必要な数値を得るようにします。
例えば 'Y' は年を、'm'は月を、'd'は日を取得する「format文字」なので

date('Y-m-d',1612088566)   

とすると
2020-01-31
という日付の文字列を得ることができるのです。😄

週の話

いや、今日は前置きが長い😅

ちょっとカレンダーを思い浮かべてほしいのですが、
もう一つ大事な基準に「1週間」というのがあります。

これをphpで扱いたい

今週の売り上げはいくらだった とか
前週比で90%を切った!ヤバイぜ とか。。。

しかしその計算はちょっと困ります。 週には1月とか2月とか呼びやすい名前というか「キー」が無いので。。。😳

そこで使われるのが'W'というフォーマット文字です。
さっきのタイムスタンプを

date('Y年第W週',1612088566)   

とすると 2021年第04週という文字列を得ることができます。

あは、便利!

dateに潜む罠

もう1月も終わりですね

でも気づいていただけましたか?
この話の落とし穴。

今日は1月31日で今年の第4週目だそうです。
でもすでに今年に入って4週間は過ぎているよね?
なんで第4週?

と思った方に拍手~💯

ちょっとまたうんちくを書くと
この'W'というフォーマット文字は
その年の最初の月曜日~日曜日を第1週として
その日がその年の第何週に属するか
を教えてくれるものなのです。

2021年に関していえば、
最初の月曜日(2021-01-04)から日曜日(2021-01-10)までなら'1'を
その翌週なら'2'を返してくれるのです。
だから2021-01-31の今日は'4'で明日は週が変わるので'5'になります。

では今年の元旦はどうだったかというと
2021-01-01 0:00:00 のタイムスタンプは1609455600です。
そこで

date('Y-m-d',1609455600) 

を実行すると 2021-01-01 00:00:00
ふむふむ

date('Y年第W週',1609455600) 

は 2021年第53週

えっ?😱
今年は始まったばかりなのにもう53週目?

いやいや、phpのバグではありませんよ
'Y' は年を表すので 当然 '2021'
'W' は2020-12-28(月)~2021-1-3(日)の週に属しますから
2020年の53週目なのです。

つまり、
date('Y年第W週') というような書き方は、 汎用的に軽々と使ってはいけない
のですね。
年末年始をゆっくり過ごすためにも、手を抜くのは禁物です😏。

もう一つ、53週目というのは毎年必ずあるかというとそうではありません。
52週目で終わる年もありますからそこも気をつけたいですね。

最後に正解は

その日付から正しい「年-週」を求めるには例えばこんな風に書きます。

date('Y-W', strtotime({{日付}}) - (date('N', strtotime({{日付}})) - 1) * 60 * 60 * 24);

意味は、
「その日の週の月曜日の日付を使って年-週のフォーマットを取得する」
です。

エンジニアのみなさん、phpの週の扱いで怪我をしないように


Hikaru