日付・時刻のテスト観点|見落としがちな境界と時差

「日付なんて単純な項目だから、テストは軽くていい」——そう考えて後で痛い目に遭った経験は、開発の現場でよくある話ではないでしょうか。日付や時刻は一見わかりやすい入力項目に見えますが、実際には月末・年またぎ・うるう年・日跨ぎ・タイムゾーン差など、境界となる条件が非常に多い領域です。ここを甘く見ると、集計のズレや二重処理、期限の誤判定といった形で、本番リリース後に静かに事故が起こります。
しかも日付バグは、テスト実施日には再現しないことが多く、特定の日を迎えて初めて表面化します。だからこそ、思いつきでケースを作るのではなく、観点を地図として体系的に持っておくことが欠かせません。
この記事では、受託開発のPMやテスト担当が押さえておくべき日付・時刻のテスト観点を、体系的に整理します。単なる技法の解説ではなく、「どこに境界が潜んでいて、なぜ事故るのか」「何を確認すればいいのか」を、チェックリストと具体例つきでまとめました。リリース直前に慌ててテスト項目を洗い出す前に、俯瞰的な地図として使っていただければと思います。
なぜ日付・時刻のテスト観点は本番事故に直結するのか
日付まわりのバグが厄介なのは、開発中やレビュー時には見つかりにくく、特定の日付を迎えて初めて表面化する点にあります。テスト実施日が月の中旬であれば、月末や年またぎの不具合はそもそも再現しません。時間が経ってから、しかも本番環境で顕在化するのが日付バグの典型です。
日付・時刻のバグは「今日テストして問題がなかった」ことが、明日の正常動作を保証しないという特殊な性質を持ちます。この非同期性こそが、見落としの温床になります。テスト計画の段階で、いつ・どの日付条件を再現するかを意図的に設計しなければ、境界は素通りしてしまうのです。
事故に直結しやすい理由を整理すると、次のようになります。
- 境界条件が桁違いに多い:月末は28・29・30・31日と月によって変わり、年またぎ・年度またぎ・うるう年・四半期の切れ目まで含めると、確認すべき境界が一気に膨らむ
- 環境に依存する:サーバー・データベース・クライアント端末・ブラウザで、それぞれ時刻やタイムゾーンの設定が異なり、環境をまたぐと値がズレる
- 時間が経たないと再現しない:締め時刻・日次バッチ・有効期限など、実時間の経過が絡む処理は、テスト環境で意図的に時刻を動かさないと検証できない
- 影響が広範囲に及ぶ:日付は集計・請求・通知・権限・ログなど多くの機能の前提になっており、1つのズレが複数機能へ波及する
日付バグが生む「実害」の具体例
抽象的に「バグが出る」と言われてもピンと来ないかもしれません。日付・時刻の不具合が、実務でどんな損害につながるかを表に整理します。
| 事象の種類 | 起きること | 想定される実害 |
|---|---|---|
| 集計ズレ | 日付境界の切り出しを1日間違える | 月次売上や稼働時間の数字が合わず、請求・報告に影響 |
| 二重処理 | 日次バッチが日跨ぎで2回走る | 同じデータを2回処理し、ポイント付与や決済が重複 |
| 表示ズレ | 保存時刻とタイムゾーンが噛み合わない | 海外ユーザーに前日・翌日の日付が表示される |
| 期限誤り | 「N日後」の計算が境界でずれる | 契約期限やキャンペーン終了を1日早く/遅く判定 |
| 権限誤り | 有効期間の判定が閉区間・開区間で食い違う | 期限当日にアクセスできない、または過ぎても使える |
日付の1日のズレは、金額や権限の判定に直結すると、そのままクレームや損害賠償のリスクに変わります。だからこそ、日付・時刻は「単純だから軽く」ではなく「単純に見えて事故りやすいから重点的に」テストすべき領域なのです。
こうした不具合は、リリース直後には気づかれず、締め日や決算期を迎えたタイミングで一斉に発覚することが少なくありません。発覚が遅れるほど、蓄積された誤ったデータの補正コストも膨らみます。
日付バグの根っこは「境界の扱いミス」
日付バグの多くは、境界値の扱いミスに起因します。境界に欠陥が集中するのは経験則として広く知られており、リー・コープランド『ソフトウェアテスト技法』でも「境界にはたくさんの欠陥が潜んでいる」と指摘されています。日付はまさに境界の宝庫であり、境界値という視点を持つだけで検出できるバグが数多くあります。
不等号の向きを1つ間違える、< と <= を取り違える、といった小さなミスが、月末や締め時刻という境界でだけ牙をむきます。技法そのものの基礎は境界値分析のやり方と具体例で詳しく解説していますので、あわせて確認してください。
日付の境界で押さえるべきテスト観点
まず最初に押さえたいのが、日付そのものが持つ境界です。ここは網羅すべきパターンがある程度決まっているため、チェックリスト化して機械的に潰していくのが有効です。
月末・月初と月の日数の違い
月末は月によって日数が変わります。31日ある月、30日の月、そして2月という三者三様の境界を、それぞれテストする必要があります。
- 31日の月:1・3・5・7・8・10・12月。月末日として31日を入力・処理できるか
- 30日の月:4・6・9・11月。31日を渡したときのエラー処理やクランプ(30日への丸め)が仕様どおりか
- 2月:平年は28日、うるう年は29日。存在しない2月30日・2月29日(平年)の扱い
- 月初:1日の0時ちょうど、前月末からの繰り越し処理
「毎月15日に実行」のような仕様でも、月末締めや月初処理が絡む機能では、必ず31日・30日・2月の3パターンを確認すべきです。
特に「毎月末に実行」という仕様は要注意です。月末が28日なのか31日なのかを固定値で実装してしまうと、月によって処理日がずれます。月末は「その月の最終日」として動的に求める必要があり、ここは実装とテストの両面で確認すべきポイントです。
存在しない日付・不正な日付の入力
境界のテストでは、正しい日付だけでなく、存在しない日付を渡したときの挙動も確認します。入力フォームやAPIで不正な日付を受け取ったとき、システムが黙って別の日に丸めてしまうと、利用者の意図と異なる結果になります。
| 入力 | 期待される挙動の例 | 危険な挙動 |
|---|---|---|
| 2月30日 | 入力エラーとして弾く | 3月2日に自動繰り上げ |
| 平年の2月29日 | 存在しない日として拒否 | 3月1日に丸めて登録 |
| 4月31日 | バリデーションエラー | 5月1日として保存 |
| 13月1日 | 明確なエラー返却 | 翌年1月に暗黙変換 |
不正な日付を黙って有効な日付へ丸める実装は、利用者が気づかないまま誤ったデータを生むため、境界テストで必ず洗い出すべき危険なパターンです。
うるう年の判定ルールを正確にテストする
うるう年の判定は、意外と実装ミスが起きやすいポイントです。ルールは次のとおりで、単純な「4で割り切れる年」だけでは不正確です。
| 条件 | 判定 | 例 |
|---|---|---|
| 4で割り切れる | うるう年 | 2024年・2028年 |
| 4で割り切れるが100で割り切れる | 平年 | 1900年・2100年 |
| 400で割り切れる | うるう年 | 2000年・2400年 |
つまり2000年はうるう年ですが、1900年と2100年は平年です。「4で割り切れれば必ずうるう年」という誤実装は、100年・400年の例外を踏むまで発覚しないため、境界年を狙ってテストすることが重要です。2月29日を有効日として登録・計算・表示できるか、平年に2月29日を渡したときのエラー処理まで含めて確認します。
うるう年は4年に1度しか訪れないため、テスト実施日がうるう年でない場合、システム日時を固定しないと検証そのものができません。この点は後述する「システム日時の固定」と密接に関わります。
年またぎ・年度・四半期の境界
暦の上の1年だけでなく、業務上の区切りも境界になります。
- 年またぎ:12月31日23時59分59秒から1月1日0時への遷移。年をまたぐ集計・連番のリセット
- 年度またぎ:日本の会計年度は多くが4月1日始まり。3月31日と4月1日で年度が切り替わる集計
- 四半期の境界:四半期集計・締め処理での区切り
- 和暦・西暦:元号をまたぐ日付の表示、和暦での年の扱い
年度は西暦の年またぎとズレるため、「年またぎは大丈夫だったのに年度またぎで事故る」というパターンが起こります。集計や締めの機能では、両方を独立した観点として持っておく必要があります。連番のリセットや期首残高の繰り越しなど、年度境界でしか動かないロジックは、テストでも意図的に年度をまたがせて確認します。
一日の中の時刻境界と締め時刻
日付だけでなく、一日の中の時刻にも境界があります。
- 0時ちょうど:日付が変わる瞬間。日次処理の基準時刻
- 23時59分59秒:その日の最後。秒・ミリ秒まで含めた締めの範囲
- 締め時刻:「当日18時締め」のような業務上の区切り。締め直前・直後・ちょうどの3点
締め時刻の判定では、「18時00分00秒」を締めに含めるか含めないか(境界の開閉)で結果が変わります。ここは仕様を曖昧なままにせず、開区間・閉区間のどちらなのかを明確にしてテストすべきです。ECサイトの注文締めや在庫の切り替えなど、日付境界が実際にどう事故につながるかはECサイトのテスト観点と確認項目でも具体的に触れています。
タイムゾーンと時差・サマータイムのテスト観点
日付まわりの中でも、特に見落とされやすく、かつ影響が大きいのがタイムゾーンです。国内向けサービスでも、サーバーの設定やクラウドのデフォルトTZが原因で、思わぬズレが生まれます。
UTCとローカル時刻の取り違え
タイムゾーンのトラブルの根本原因は、UTC(協定世界時)とローカル時刻の変換ミスです。基本原則は保存はUTC、表示はローカルという一貫したルールを、システム全体で徹底することです。
確認すべき観点を整理します。
- サーバーのタイムゾーン設定:本番・ステージング・開発でTZ設定が揃っているか
- データベースのTZ設定:DBが保存する時刻がUTCか、ローカルか。接続時のセッションTZ
- アプリケーションの変換:保存時にUTCへ、表示時にローカルへ正しく変換しているか
- 二重変換・無変換:変換を2回かけて時刻がずれる、または変換を忘れて生の値を出す
日本国内だけを対象にしていても、クラウドの標準TZがUTCであることは多く、「開発では合っていたのに本番で9時間ずれた」という事故はよく起こります。開発環境と本番環境でTZ設定が異なると、テストをすり抜けて本番でだけ再現するため、環境間の設定差そのものを確認項目にすべきです。
時差と海外ユーザーへの対応
海外のユーザーや拠点を持つシステムでは、時差そのものが観点になります。
| 観点 | 確認すること | 該当なしの場合 |
|---|---|---|
| ユーザーのTZ | 利用者ごとにTZを設定・表示できるか | 国内単一拠点なら省略可 |
| 日付境界のズレ | UTC基準の「今日」と現地の「今日」が食い違わないか | 集計が国内基準なら影響小 |
| 日付をまたぐ表示 | 深夜帯の時刻が前日・翌日に見えないか | 時刻を表示しないなら影響なし |
| 締め時刻の基準 | 締めがどのTZ基準かが定義されているか | 全ユーザー同一TZなら単純 |
海外ユーザーがいる場合、「日本時間の今日」と「現地時間の今日」がずれるため、日次集計の対象範囲が食い違うことがあります。どのタイムゾーンを基準に「1日」を切るのかを、仕様として明確に決めておくことが重要です。
サマータイム(DST)の扱い
サマータイム(夏時間、DST)は、日付まわりのテストで特に注意が必要な領域です。日本では現在サマータイムは通常運用されていませんが、海外向けサービスや過去データを扱う場合には避けて通れない観点です。
サマータイムのある地域では、切り替えの際に次のような特殊な現象が起きます。
- 存在しない時刻:春の切り替えで時計が1時間進み、例えば午前2時台が丸ごと存在しない日がある
- 重複する時刻:秋の切り替えで時計が1時間戻り、同じ時刻が2回訪れる日がある
- 1日の長さの変化:切り替え日は23時間または25時間になり、「1日=24時間」の前提が崩れる
これらは「存在しない時刻に予約が入る」「重複時刻でどちらの回か判別できない」といった不具合につながります。海外拠点向けの機能では、切り替え日を狙ったテストが必須です。標準時やうるう秒など時刻の基準に関する正確な情報は、国立研究開発法人情報通信研究機構(NICT)のQ&Aが参考になります。
なお、うるう秒(不定期に挿入される1秒)も過去にシステム障害を引き起こした例があります。国際的には2035年までにうるう秒を廃止する方向で合意がなされていますが、既存システムの過去データや秒精度の処理では、念のため考慮しておくとよいでしょう。
相対日付・期間計算のテスト観点
固定の日付だけでなく、「基準日からN日後」のように計算で求める日付も、境界で狂いやすい領域です。ここは境界値と同値分割の考え方が特に効きます。同値分割の基礎は同値分割法のテストケース作成手順で解説しています。
期間計算・期限計算で狂いやすい点
「N日後」「N営業日後」といった計算は、月またぎ・年またぎ・うるう年をまたぐと結果が変わります。
- N日後・N日前:月末・年末・2月29日をまたぐ計算。30日後が翌月の何日になるか
- 営業日計算:土日・祝日を除外する計算。年末年始や連休をまたぐケース、祝日マスタの更新漏れ
- 有効期限:「登録日から30日間有効」の起算日と満了日。当日を含むか含まないか
- 経過時間:2つの日時の差分。日跨ぎ・TZ跨ぎでの時間・日数の計算
期限計算では「起算日を含むか」「満了日を含むか」の1日の解釈違いが、そのまま権利や請求の範囲のズレになります。仕様の言葉を鵜呑みにせず、境界日で実際の判定結果を確認することが欠かせません。
祝日を扱う営業日計算では、祝日マスタのメンテナンスも観点になります。法改正で祝日が移動・追加されることがあり、マスタの更新が漏れると営業日計算が静かにずれます。祝日データの鮮度も、テストと運用の両面で確認しておきましょう。
通知メールやリマインダーの送信時刻も、相対日付が絡む代表例です。「期限の3日前に通知」「予約日の前日に確認メール」といった機能では、基準日から遡って送信日を求めるため、月またぎや連休をまたぐと送信タイミングがずれます。送信予定日が営業日か、深夜に送っていないか、二重送信や送信漏れが起きないかまで含めて、境界日を狙って確認しておくと安心です。
年齢計算という定番の落とし穴
年齢計算は、相対日付の中でも古典的かつ重要なテーマです。特に2月29日生まれの人の扱いは、実装によって結果が分かれます。
| 確認ケース | 観点 | 判定基準の例 |
|---|---|---|
| 誕生日の前日・当日・翌日 | いつ1歳増えるか | 法律上は誕生日前日の満了で加齢 |
| 2月29日生まれ | 平年の何日を誕生日扱いにするか | 2月28日か3月1日か仕様で定義 |
| 月末生まれ | 翌月に対応日がない場合の扱い | クランプの方向を明確化 |
| 未来日・過去日 | 生年月日が未来のときのエラー | 入力チェックで弾く |
年齢は会員登録の年齢制限や料金区分の判定に使われることが多く、1歳の判定ミスが「本来使えるはずの人が弾かれる」不具合に直結します。境界日を狙って必ず検証しましょう。年齢制限のあるサービスでは、判定を1日間違えるだけで法令やサービス規約に抵触する恐れもあり、優先度を上げて確認すべき観点です。
保存・表示とシステム間連携での日時の扱い
日付・時刻は、システム内部での保存形式、画面での表示、外部システムとの連携という3つの層で、それぞれ異なる観点が必要です。
保存はUTC・表示はローカルの原則
前述のとおり、時刻データは内部ではUTCで一貫して持ち、画面表示の直前にローカルへ変換するのが定石です。
- 保存形式の統一:全テーブル・全APIで時刻の持ち方(UTC・タイムゾーン付き)を統一する
- 表示フォーマット:
YYYY/MM/DDとYYYY-MM-DD、12時間制と24時間制、和暦・西暦の表記ゆれ - 入力パース:ユーザーが入力した日付文字列をどのTZ・書式として解釈するか
- ロケール:曜日・月名・区切り文字の地域差
表示フォーマットの不統一は、バグではなくとも品質の印象を大きく下げるため、画面横断で書式を統一しておくべきです。画面ごとに日付の書式がバラバラだと、利用者は違和感を覚えるものです。特に和暦と西暦の混在や、月日のゼロ埋めの有無といった細かな差は、帳票や公的な書類を扱う画面で目立ちます。
ログ・監査での時刻の一貫性
見落とされがちですが、ログや監査証跡の時刻も重要な観点です。障害調査やトラブル対応の際、ログの時刻がバラバラだと、事象の前後関係を正しく追えなくなります。
- ログのTZ統一:複数サーバーのログが同じ基準(UTC推奨)で記録されているか
- 時刻同期:サーバー間の時刻がNTPなどで同期されているか
- 精度:ミリ秒単位のイベント順序が判別できる精度か
- 監査要件:監査上、記録すべき時刻の粒度と保持期間を満たしているか
システム間連携での日時フォーマット
外部システムやAPIとの連携では、日時の受け渡しでズレが生まれやすくなります。連携時のデータの一貫性という観点は、データ整合性テストの進め方とも密接に関係します。
連携で最も危険なのは、タイムゾーン情報が欠落した日時文字列を、送信側と受信側が別々のTZで解釈してしまうケースです。
連携時に確認すべき観点は次のとおりです。
- フォーマットの合意:ISO 8601など、日時文字列の書式を両システムで合意しているか
- タイムゾーンの明示:送受信する日時にTZ(オフセットやUTC表記)が含まれているか
- 精度の一致:秒・ミリ秒までの精度が、送信側と受信側で揃っているか
- 境界データの往復:月末・年またぎ・うるう年の日時を送受信して、値が保たれるか
TZが欠落した日時をやり取りすると、片方がUTC、もう片方がローカルと解釈し、静かに数時間ズレたデータが蓄積されます。連携仕様のレビュー段階で、日時のフォーマットとTZの扱いを必ず確認しておきましょう。
日付・時刻のテスト観点を体系的に洗い出す進め方
ここまで挙げてきた観点を、実際のテストにどう落とし込むかを整理します。観点は数が多いため、場当たり的にケースを作ると必ず漏れます。進め方を仕組みにすることが大切です。
システム日時の固定・モックが前提になる
日付テストの最大の壁は、「未来の日付や特定の日付を、テスト実施日に再現できない」ことです。これを解決するのが、システム日時の固定・モックです。
- システム日時の注入:現在日時を直接参照せず、差し替え可能な仕組み(時刻プロバイダ)を通す設計にする
- 時刻の固定:テスト実行時に「2024年2月29日23時59分59秒」のような任意の時刻へ固定する
- 時刻を進めるテスト:締め時刻や日次バッチのために、時刻を意図的に進めて日跨ぎの挙動を確認する
- 環境TZの切り替え:異なるタイムゾーン設定で同じテストを実行し、結果が仕様どおりか比較する
システム日時を差し替えられる設計になっているかどうかで、日付テストの実行可能性は大きく変わります。これは開発初期に設計へ織り込むべき事項であり、テスト段階で慌てて対応しようとすると手戻りが大きくなります。設計レビューの段階で、時刻の取得箇所が一元化されているかを確認しておくと安心です。
境界値・同値分割で観点を漏らさない
観点の洗い出しには、テスト設計技法をそのまま活用できます。日付は境界の塊なので、境界値分析と同値分割が特に有効です。
| 技法 | 日付・時刻への適用 | 具体例 |
|---|---|---|
| 境界値分析 | 境界の直前・境界・直後を狙う | 2月28日/29日/3月1日 |
| 同値分割 | 同じ扱いになる日付をグループ化 | 31日の月・30日の月・2月 |
| デシジョンテーブル | 曜日×祝日×締め時刻の組合せ | 営業日計算の条件整理 |
| 状態遷移 | 時刻経過で変わる状態 | 有効→期限切れの遷移 |
これらの技法を機械的に当てはめるだけでも、感覚頼みのテストより網羅性は格段に上がります。技法ごとに「日付に適用するとどうなるか」をチームで共有しておくと、担当者による観点のばらつきも抑えられます。
実務で使える確認チェックリスト
最後に、リリース前に点検するための確認項目をチェックリストにまとめます。月曜からそのまま使える粒度で整理しました。
- [ ] 月末(31日・30日・2月)の3パターンを確認したか
- [ ] うるう年(2000年型・1900年型・通常のうるう年)を確認したか
- [ ] 存在しない日付(2月30日など)のバリデーションを確認したか
- [ ] 年またぎ・年度またぎ・四半期の境界を確認したか
- [ ] 0時・23時59分59秒・締め時刻の境界を確認したか
- [ ] サーバー・DB・クライアントのTZ設定が意図どおりか確認したか
- [ ] 保存はUTC・表示はローカルの原則が守られているか確認したか
- [ ] 海外TZ・サマータイム(該当する場合)を確認したか
- [ ] N日後・営業日・有効期限・年齢の境界計算を確認したか
- [ ] ログ・監査の時刻がTZ統一・時刻同期されているか確認したか
- [ ] 外部連携の日時フォーマットとTZ明示を確認したか
- [ ] システム日時を固定・モックしてテストできる状態か確認したか
このチェックリストを、案件ごとのテスト観点表のベースにすれば、抜け漏れを大きく減らせます。テスト設計の技法そのものの権威ある解説は、JSTQB(日本のソフトウェアテスト技術者資格認定機関)の公式サイトも参考になります。
まとめ:日付・時刻のテスト観点を「地図」として持つ
日付・時刻は、単純に見えて境界と環境依存が多く、本番で静かに事故が起きやすい領域です。だからこそ、場当たり的にテストするのではなく、境界・タイムゾーン・相対計算・保存表示・連携・実行方法という軸で、日付・時刻のテスト観点を地図として体系的に持っておくことが有効です。
最後に、本記事の要点を3つに絞って振り返ります。
- 境界を先回りする:月末・うるう年・年またぎ・締め時刻など、事故の起点は境界に集中している
- 環境差を疑う:サーバー・DB・クライアントのTZ設定の食い違いが、本番だけで再現するズレを生む
- 再現できる設計にする:システム日時を固定・モックできて初めて、未来の日付も安定して検証できる
重要なのは、日付バグは「今日問題がない」ことが「明日の正常」を保証しないと理解し、境界日を狙って先回りしてテストすることです。本記事のチェックリストを起点に、案件ごとの事情を足し引きしながら、自社のテスト観点表を育てていってください。
とはいえ、これらの観点をすべて自社で網羅し続けるのは、兼任中心のテスト体制では負担が大きいのも事実です。テスト観点の抜け漏れや、境界条件の洗い出しに不安を感じている方は、テスト体制の見直しについて気軽に相談するところから始めてみてはいかがでしょうか。第三者の視点が入ることで、見落としがちな境界が見えてくることもあります。
次に読むならこの記事
テストの手戻りを減らしたい方へ
テスト仕様書のExcelテンプレートを無料で配布しています。自社で整備する場合も、外部に任せる場合も、まずは型を持つところから。



