SheepDev

日時・スケジュール

月末の1か月後はいつ?30日後とは違う?

使うツール

『一か月後まで有効』と『30日間有効』は、同じつもりで使われがちです。しかし1月31日から数えると、すぐに答えが分かれます。日付の計算で難しいのは足し算そのものより、何を一単位と考えるかです。月、暦日、経過時間を分けると、仕様に書かれていなかった約束事が見えてきます。

ここでは日時の加減算と日時差計算を使います。契約条件を自動判定するツールではないため、まず既存の規則が『翌月の同日』『翌月末』『一定時間後』のどれなのかを確認します。決まっていない場合は、計算結果を見て都合のよい方を採るのではなく、その違いを仕様の検討材料にしてください。

1月31日から一か月と30日を足す

入力日時。比較中のタイムゾーンはUTC
2024-01-31T12:00:00Z

日時の加減算で月を1、ほかの加算を0、月末処理を日付の制約に合わせる設定にすると、2024年2月29日12時になります。2024年はうるう年ですが、2月31日は存在しないため、存在する最後の日へ合わせます。同じ元日時から月を0、日を30にすると3月1日12時です。一か月を30日へ置き換えただけで、この例では一日の差になります。

年だけを2023年へ変えると、一か月後は2月28日、30日後は3月2日になります。同じ入力項目でも、年によって差は変わります。一年分の日数を固定して月の長さを平均化する方法では、実際の更新日を再現できません。表示する年を省略するとこの違いが見えにくいため、比較結果には年月日をそろえて残します。

補正するか、入力条件を拒否するか

月末処理を拒否へ変えると、1月31日への一か月加算はエラーになります。これは計算機の故障ではなく、存在しない日を勝手に別の日へ置き換えない規則です。自動補正を許す場面でも、結果が月末へ変わったことを理解して使います。『翌月の31日がなければ受付不可』という仕組みと、『なければ月末』という仕組みを同じ計算として扱わないでください。

2月29日に一年を足す場合にも同じ判断が必要です。2024年2月29日から2025年2月へ移すと、その月に29日はありません。誕生日、更新日、集計の締め日など、用途によって決め方は違います。このツールは選択された制約方式を適用するだけで、用途から規則を推測しません。

一か月を二回足すと、二か月を一回と違う

2024年1月31日を起点に、制約方式で比較
Jan 31 + 1 month = Feb 29
Feb 29 + 1 month = Mar 29
Jan 31 + 2 months = Mar 31

一回目の補正で日付は29日に変わっています。その結果を次回の元データにすると、次は3月29日になります。元の31日を記憶して、三月には自動的に31日へ戻す仕組みではありません。毎月末の予定を作るつもりなら、前回の結果へ一か月ずつ足すだけでは不足します。毎回起点から計算するのか、月末を選び直すのかを、繰り返し予定の規則として定義します。

引き算でも元へ戻る保証はありません。1月31日から一か月進めて2月29日になり、そこから一か月戻すと1月29日です。これは情報が失われる補正を含むためです。金額の足し算と引き算のように逆演算で必ず復元できると考えず、元の日付を必要な検証データとして残しておきます。

一日後が、24時間後ではない日

America/New_Yorkで比較する元日時
2024-03-09T12:00:00-05:00

タイムゾーンをAmerica/New_Yorkにして日を1足すと、3月10日12時、オフセット-04:00になります。時計が進む切替をまたぐので、経過時間は23時間です。一方、日を0、時間を24にすると3月10日13時になります。どちらも正しい計算ですが、維持しているものが違います。毎日の昼食の予定なら現地の12時、機器の連続稼働時間なら24時間というように、目的から単位を選びます。

この実験は日付、地域、元のオフセットをそろえることが大切です。同じ数字の12時でも、UTCの12時とニューヨークの12時は別の瞬間です。また、月末の補正設定は夏時間の曖昧な時刻の選択設定ではありません。切替時刻そのものを予約したい場合は、タイムゾーン変換の現地時刻モードで存在・重複を別途確認します。

日付の差と、経過時間を同じ欄で読まない

日時差計算の暦日モードで2024-03-09と2024-03-10を比べると1日です。経過時間モードで2024-03-09T12:00:00-05:00と2024-03-10T12:00:00-04:00を比べると23時間、82,800秒です。日付だけの入力にタイムゾーンや時刻を勝手に補って24時間と解釈しないことが、この二つのモードを分ける理由です。

さらに、3月9日から10日までを『両日とも対象にする』と、対象となる日付は二つです。日付の差が1であることと、期間に含む日を二つ数えることは矛盾しません。営業日を数えたい場合は端点を含むかを選べる営業日計算へ進み、経過日数をそのまま対象件数にしないようにします。

期限の仕様に必要なのは、数字より先に規則

確認メモには、起点の日時、タイムゾーン、加える単位、月末処理、繰り返し時の起点を残します。『一か月後』という結果だけでは、翌月に同じ計算を再現できません。月末、うるう年、夏時間のある日を一つずつ試すと、普通の日には見えなかった差を短時間で確認できます。

このツールは予定を登録したり、実サービスの更新日を取得したりしません。計算結果が既存サービスと違ったときは、まずどの規則が違うのかを比較します。入力日時が同じなら常にサービスが間違っている、と判断するためのものではありません。規則を説明できることが、日付の数字が一つ出ることより大切です。

毎月の基準日は、前回結果から作るとは限らない

1月31日を基準に、毎月の予定を作りたいとします。一か月加算で2月末へ補正した結果に、また一か月を足すと、3月もその日付になる場合があります。一方、元の1月31日から二か月後を求めると3月31日です。契約が『毎月末』なのか、『元の日を保ち、存在しない月だけ補正』なのか、『前回の結果から一か月』なのかを決めないと、同じ加算ツールでも入力手順で違う予定を作れます。単に月末補正を有効にしただけでは、繰り返し予定の仕様は確定しません。

有効期限を作る場合には、日付に加えて終了時点も必要です。『3月31日まで』と『3月31日0時まで』は同じ期間ではありません。日付だけを扱う計算結果へ、勝手に一日の終わりや始まりを付け足すと、利用者が使える時間が変わります。どのTimezoneの時刻か、終了を含むか、秒未満をどう扱うかはサービスの仕様として確認します。日時の計算はその決めた規則を再現する工程であり、文言の曖昧さを自動解決するものではありません。

確認例は、普通の日だけでなく1月末、うるう年の2月、夏時間をまたぐ日を用意します。それぞれで元の日付、加える単位、補正方針、期待結果を残せば、月と日と時間を取り違えた変更を見つけやすくなります。結果を元へ引き戻す往復確認も役立ちますが、月末補正で日付の情報を失った場合は、必ず元へ戻るとは限りません。往復しないこと自体が不具合なのか、指定した補正の結果なのかを区別して読みます。

参考資料

使うツール

使い方・解説 →