Septemberは7なのに9月、Octoberは8なのに10月。
日付は身近なものではありますが、
過去の歴史やしがらみから認識誤りが発生しやすい分野です。
簡単なチェック
-
日付や期間について、複数パターンの図を描いて合意したか
-
日付や期間について、複数パターンの実例を書いて合意したか
-
期間について、いつ始まり、いつ終わるか秒単位で合意したか
-
ひと月あたりの日数の違いは考慮しているか
1/31, 2/28, 3/31... -
うるう年は考慮しているか
-
24:00
をまわった場合は前日分と当日分、どちらとしてカウントするか
-
営業日ベースか、日数ベースか
-
その仕様は試験 / 検証可能か
日付や期間について、図と実例で合意したか
ある日の夜間、1週間後とは具体的に何月何日の何時何分何秒...地球が何回回ったときでしょうか?
例えば3/3から3日間とすると、終わりは3/6まで? 3/5まで? 3/6の23:59:59.9999まで?始まりは?
だいたい関係者間で認識がずれているので、図や実例をいろんなパターンで書いてみましょう。
月と年:日数が安定しない
期間1ヶ月で! → 31日ある月もあれば、30日の月もあり、28日しかない月もある。
30日合計分と31日合計分を比較すると、1日だけの違いとはいえ約3%のずれがあります。
ラウンドトリップ問題
1/31の1ヶ月後は? 2/28? さらにそこから1ヶ月戻すとどうなる?
法令による業務仕様の場合、その法令の解釈も検証する必要があります。
1年も注意が必要です。うるう年を忘れずに。
対応例:
- うまくカレンダー通りにする
- 365日で固定させる
- 360日(30日 × 12ヶ月)で固定させる
"1日"の定義:どこからどこまでか
1日分も簡単そうで紛らわしいです。
- あるタイミングから24時間
- その日の
24:00
まで
おそらくどちらかだと思います。
なお、消費者向けのアプリケーションの場合、
24時を超えてもアクセスはたくさん来ます。
特に主な顧客が国内の場合、24:00
をまわった分は当日分と翌日分、どちらとしてカウントするか決めておきましょう。
参考
営業日ベース vs 日数ベース
社内業務系の場合、平日のみ(営業日)で日数を数えることはよくあります。
この場合祝日のマスタ管理が必要になります。
必要なら日本以外の祝日も管理しましょう。
試験 / 検証可能か
3日後に動作する仕様を試験するのに、本当に3日待たないといけない仕様になっていませんか?
だからといってOSの日付を操作してなんとかしようすると、様々な部分がおかしくなります。
日付周りはパラメータなどの何らかの形でコントロールできるとうれしいですね。
システム的にはnow()
といった状態依存のメソッドの乱用は控えるとよいでしょう
わかりやすい例
- https://t-wada.hatenablog.jp/entry/design-for-testability
https://codeiq.jp/magazine/2013/11/1475/- https://nekoya.github.io/blog/2013/07/09/what-time-is-it/
細かいもの
サマータイム
海外向けのフロントエンドを作る場合は考慮を忘れずに
時差
昼にメールを送ったつもりが現地の深夜に届くかもしれません。
年号
Web系なら年号を使っているとしてもフロントエンドでの変換ぐらいなので問題ないでしょう。
システム関連携で年号を保持しているとつらいですね。
個人的には新年号がJISやunicodeに加わるか気になります。
㍾ ㍽ ㍼ ㍻ の次。
以下の話はしません
- 太陽太陰暦による春節の算出
- 修正ユリウス暦のうるう年算出
- 天文時
- イラン歴
その他システム的観点
うるう秒
最近はntpサーバがよしなにしてくれます。
よしなにしていない場合は注意
unixtime
2038年問題はよく知られていますが、日付同士を加算しても起こりえます。
その場合は(日付A + 日付B) / 2
ではなく、(日付A / 2) + (日付B / 2)
に。
タイムゾーン
OS、言語、ライブラリ、ミドルウェアごとに
どのタイムゾーンを扱っているのか、扱えるのかが異なる可能性があります。
わからなくなったら全部書き出してみましょう。
最後に
要件の誤りはテストではなかなか見つかりません。
認知の問題で一番検討が難しいのでみなさん頑張りましょう。