海外の同僚とミーティングを設定したら、相手が 1 時間早く来た。バッチ処理の実行時刻が日によってズレる。ログに出ている時刻がサーバー時刻なのか UTC なのか分からない。日付・時刻の世界は、表面は平和なのに踏み込むと底なし沼です。タイムゾーン、サマータイム、うるう秒、そして 2038 年問題。本記事では、ISO 8601 から UNIX 時間、曜日計算、営業日カウントまで、実務で日付を扱うときに必ずどこかで引っかかる論点を順番に整理します。ベンリーの 世界時計・カレンダー・時刻フォーマット・曜日まで何日 の 4 ツールとあわせて、日付・時刻に強くなりましょう。
UNIX 時間の起点(エポック)が 1970-01-01 00:00:00 UTC になっているのは、Bell Labs で UNIX が開発されていた当時の成り行きです。初期の UNIX(1971 年ごろのマニュアル)ではシステム時刻を 1971-01-01 からの 60 分の 1 秒単位で数えていましたが、32 bit で表現できる範囲がすぐに埋まってしまうため、秒単位に変更し、同時に起点を「キリの良い年初」である 1970-01-01 にスライドさせました。特別な哲学的理由があって選ばれたわけではなく「便宜上いちばん近い年初」だったわけです。その結果、32 bit signed int で秒を数える実装は 2^31 − 1 秒後の 2038 年 1 月 19 日 03:14:07 UTC に桁あふれを起こします。これがいわゆる 2038 年問題(Y2K38)で、現代の OS・言語・DB はほぼ 64 bit 化されて解消していますが、組み込み機器や古いファイルフォーマットには今も残っています。
ISO 8601 の基本
日付を文字列でやり取りするとき、最も安全で異論の少ないフォーマットは ISO 8601 です。2026-04-15、2026-04-15T09:30:00+09:00、2026-04-15T00:30:00Z のように「大きい単位から小さい単位へ」並べるルールが特徴で、文字列のまま辞書順でソートすると時系列順にもなるという嬉しい性質があります。API のレスポンスに日時を入れるときは、何も考えずに ISO 8601 にしておけばまず間違いありません。
ISO 8601 には書き方のバリエーションがいくつかありますが、覚えておくべきパターンは次の 5 つです。
| パターン | 例 | 用途 |
|---|---|---|
| 日付のみ | 2026-04-15 | 日付しか必要ないフィールド(生年月日、請求日など) |
| 日時 + Z | 2026-04-15T00:30:00Z | UTC であることを明示。サーバー間通信の定番 |
| 日時 + オフセット | 2026-04-15T09:30:00+09:00 | 現地時刻を保持したいログ、ユーザー向け表示 |
| 週番号 | 2026-W16-3 | 週単位の進捗管理、製造業のロット番号 |
| 連続日付 | 2026-105 | 年間通算日(DOY)。気象・天文データ |
基本形式(basic format)と拡張形式(extended format)の違いにも触れておきます。拡張形式はハイフンとコロンで区切る人間に読みやすい表記、基本形式は区切り文字を省いた 20260415T093000Z のような表記です。拡張形式が圧倒的に普及していますが、ファイル名には区切り文字を使えないため基本形式が選ばれることがあります。どちらも同じ規格なので、混在させないことだけ気をつけてください。
迷ったら YYYY-MM-DDTHH:mm:ss.sssZ(ミリ秒 + UTC の Z 付き)を使いましょう。JavaScript の new Date().toISOString() の出力と完全に同じ形で、すべての主要言語でパース可能です。自前で文字列をいじるよりも標準ライブラリを信頼するほうが安全です。
UNIX タイムスタンプ
UNIX 時間(POSIX 時間、エポック秒)は、1970-01-01 00:00:00 UTC からの経過秒数を 1 つの整数で表したものです。タイムゾーンを含まないため、世界中どこでも同じ値になります。サーバーのログや DB の created_at カラムで広く使われていて、算術演算(「30 日前」「1 時間後」など)がただの足し算引き算で済むのが最大のメリットです。
主要言語での取得方法は次のとおりです。
// JavaScript(秒単位)
Math.floor(Date.now() / 1000) // 例: 1776384000
// JavaScript(ミリ秒単位、Date.now と同じ)
Date.now() // 例: 1776384000123
// Python
import time
int(time.time()) // 例: 1776384000
// Ruby
Time.now.to_i // 例: 1776384000
// シェル
date +%s // 例: 1776384000注意すべきは 単位が秒かミリ秒かの混在です。JavaScript の Date.now() はミリ秒を返しますが、他の多くの言語や DB のタイムスタンプ型は秒を返します。APIの引数として受け取るときは「10 桁なら秒、13 桁ならミリ秒」と桁数で判定するか、ドキュメントに epochMs や epochSeconds と明記するのが安全です。桁数を間違えると 1000 倍ズレるので、ユニットテストで必ずガードしましょう。
UNIX 時間の知っておくべき癖がもう 1 つあります。うるう秒(leap second)を含まないという設計です。UTC はときどき 23:59:60 という「61 秒目」を挿入してうるう秒を処理しますが、UNIX 時間の世界では 23:59:59 が 2 回繰り返されるか、同じ値が 2 度出現するかの実装依存な挙動になります。Google などは「smear」と呼ばれる手法で、数時間にわたって時計をわずかにゆっくり進めることでうるう秒を吸収しています。天文観測や高精度金融取引でない限り、アプリ開発者がうるう秒を気にする必要はほぼありません。ただし「1 秒ぴったりの間隔で実行されるジョブ」は、うるう秒を含む日に挙動が不定になる可能性があるので、ジョブスケジューラが UTC ベースなのかシステム時計ベースなのかは確認しておきましょう。
そして冒頭の情報ボックスでも触れた 2038 年問題。32 bit signed int で秒を数える実装は 2038-01-19 03:14:07 UTC に上限に達します。2026 年時点で主要な OS・言語はすべて 64 bit(int64_t の time_t)に移行済みですが、IoT 機器・古い DB・レガシーバイナリフォーマットにはまだ 32 bit の痕跡があります。組み込み機器の開発者は要注意です。
タイムゾーンとオフセット
「タイムゾーン」と「オフセット」はよく混同されますが、別物です。オフセットは +09:00 のように UTC との差分を表すただの数値で、「今この瞬間、この地点は UTC より 9 時間進んでいる」という情報しか持ちません。タイムゾーンは Asia/Tokyo のように地域名を持ち、「その地域が過去から未来に向けてどんなオフセットのルールに従うか」を表す、より大きな概念です。
この違いが効いてくるのがサマータイムの扱いです。America/Los_Angeles は夏季は -07:00、冬季は -08:00 に切り替わります。もし DB に -08:00 とオフセットだけを保存していたら、「翌年のこの時期は夏時間だから 1 時間ズラす」という判断ができません。地域名を保存しておけば、IANA のタイムゾーンデータベース(tzdata)が自動で適切なオフセットを計算してくれます。ユーザーのタイムゾーンを保存するときは、オフセットではなく地域名を保存するのがベストプラクティスです。
// JavaScript: 地域名指定でフォーマット
new Intl.DateTimeFormat('ja-JP', {
timeZone: 'Asia/Tokyo',
dateStyle: 'full',
timeStyle: 'long'
}).format(new Date());
// → '2026年4月15日水曜日 9時30分00秒 GMT+9'
// Python 3.9+ zoneinfo
from datetime import datetime
from zoneinfo import ZoneInfo
datetime.now(ZoneInfo('Asia/Tokyo'))
# → datetime.datetime(2026, 4, 15, 9, 30, 0, tzinfo=zoneinfo.ZoneInfo('Asia/Tokyo'))tzdata(IANA Time Zone Database)は世界中のタイムゾーンの歴史的変更を集約したデータベースで、ICU・glibc・Java・Python・Node.js などほぼすべての処理系が内部で参照しています。年に数回更新され、政府の決定(例:サモアが 2011 年に日付変更線を越えた、トルコが 2016 年に恒久的に DST を採用、北朝鮮が 2018 年に +09:00 に戻した)が反映されます。本番サーバーの tzdata が古いと、過去の日付をフォーマットしたときに実際と違う時刻が出ることがあるので、OS パッケージの自動アップデートは有効にしておきましょう。
サマータイム(DST)の罠
日本にはサマータイムがないので実感がわきにくいのですが、欧米・オセアニア・一部の中東では DST が今も使われています。DST 切り替え日は次の 2 つの奇妙な現象を生みます。
- 1 時間が消える日:春の切り替え日、2:00 になった瞬間に 3:00 にジャンプします。「2:30」という時刻はこの日だけ存在しません。
- 1 時間が 2 回来る日:秋の切り替え日、2:00 になった瞬間に 1:00 に巻き戻ります。「1:30」という時刻はこの日だけ 2 回発生します。
cron ジョブを現地時刻で設定していると、春の切り替え日には「2:30 に実行予定のジョブが実行されない」、秋の切り替え日には「1:30 のジョブが 2 回実行される」という事故が起きます。対策は単純で、cron は必ず UTC で設定し、実行内容の中でタイムゾーンを意識するのが鉄則です。Linux の cron なら CRON_TZ=UTC を crontab の先頭に書くか、systemd timer なら OnCalendar= とあわせて Persistent=true を設定しておきましょう。
DST が存在する地域のユーザーを相手にするアプリを作るなら、次の 3 つをテストケースに入れておくと良いです。① 春の切り替え日にその日の深夜を跨ぐ予約機能、② 秋の切り替え日に同一時刻を指定したときの動作、③ ユーザーが DST ありの地域から無しの地域へ引っ越したあとのカレンダー表示。特に ① と ② はプロダクション事故の定番ネタです。
実装レベルの対処としては、「ローカル時刻 + 地域名」のセットで保存しておけば、ライブラリが DST を吸収してくれます。反対に「現地時刻だけ」を保存すると、切り替え日をまたいで計算する際に 1 時間ズレます。Temporal API(2026 年現在、主要ブラウザで段階的に実装中)や Python の ZoneInfo のように、タイムゾーンを first-class に扱う API を使うのが最も安全です。
世界時計の使い方
ベンリーの 世界時計(/tools/world-clock/)は、主要都市の現在時刻を一覧表示するツールです。海外の同僚やクライアントとミーティングを調整するとき、相手の現地が朝なのか深夜なのかをひと目で確認できます。タイムゾーンの計算を暗算でやって間違えるよりはるかに速く、確実です。
世界時計を便利に使うコツは 3 つあります。
- 東京を基準に並べる:日本から見た時差で降順ソートしておけば、「どの国は今朝、どの国は夜」が直感的にわかります。
- 相手の「業務時間に収まるか」を確認する:時差だけ見て 21:00 に設定しても、相手が 22:00 就業のチームならギリギリです。現地の 9:00〜18:00 に収まる時間帯を探しましょう。
- 切り替え境界日をチェック:3 月後半・10 月後半は欧米の DST 切り替えがあるため、前後で時差が 1 時間変わります。月をまたぐ定例ミーティングはこのタイミングで再確認。
| 都市 | タイムゾーン | 標準時差(東京基準) | DST |
|---|---|---|---|
| ニューヨーク | America/New_York | −14 時間 | あり(−13 時間) |
| ロサンゼルス | America/Los_Angeles | −17 時間 | あり(−16 時間) |
| ロンドン | Europe/London | −9 時間 | あり(−8 時間) |
| パリ / ベルリン | Europe/Paris | −8 時間 | あり(−7 時間) |
| ドバイ | Asia/Dubai | −5 時間 | なし |
| 北京 / 上海 | Asia/Shanghai | −1 時間 | なし |
| シンガポール | Asia/Singapore | −1 時間 | なし |
| シドニー | Australia/Sydney | +1 時間 | あり(+2 時間) |
この表で面白いのは、シドニーが東京より「進んで」いることと、中国が広大な国土にもかかわらず全土を Asia/Shanghai で統一していることです。新疆ウイグル自治区は実質的に 2 時間ほど「早すぎる」時刻で暮らしているのですが、公式にはすべて北京時間です。タイムゾーンは純粋な経度計算ではなく、政治的な決定に強く引っ張られているということを覚えておきましょう。
曜日計算(Zeller の公式)
任意の日付から曜日を求めたいとき、プログラムなら new Date('2026-04-15').getDay() でおしまいですが、「紙と鉛筆で計算したい」という場面もたまにあります(歴史記録の検証、クイズ、面接問題など)。そのための古典的アルゴリズムが Zeller の公式です。グレゴリオ暦に対しては次のような形です。
h = (q + floor(13(m+1)/5) + K + floor(K/4) + floor(J/4) - 2J) mod 7
// h: 0=土, 1=日, 2=月, 3=火, 4=水, 5=木, 6=金
// q: 日(day of month)
// m: 月。ただし 1 月・2 月は前年の 13 月・14 月として扱う
// K: year mod 100(下 2 桁)
// J: floor(year / 100)(上 2 桁)人力でやると演算量が多いのですが、一度慣れれば 30 秒程度で任意の日付の曜日を言い当てられます。宴会芸としても優秀です。
一方プログラムで扱うときは、言語ごとの 曜日番号の基準が統一されていない点に注意が必要です。
| 言語 / API | 基準 | 月曜 | 日曜 |
|---|---|---|---|
JavaScript Date.getDay() | 日曜始まり | 1 | 0 |
Python datetime.weekday() | 月曜始まり | 0 | 6 |
Python datetime.isoweekday() | ISO 8601 | 1 | 7 |
Ruby Date#wday | 日曜始まり | 1 | 0 |
Java DayOfWeek(java.time) | ISO 8601 | 1 | 7 |
多言語でデータをやり取りするときは、ISO 8601 の「月曜 = 1、日曜 = 7」を共通規約にしておくのが無難です。特に JavaScript と Python が混ざったシステムでは、JS の getDay() と Python の weekday() はどちらも使わず、isoweekday() 相当に揃える習慣をつけましょう。
「次の金曜日まで何日?」
「今日から見て次の金曜日まで何日?」という計算は業務で地味によく出てきます。レポート提出日、支払い期日、定例ミーティングのリマインダ。ベンリーには 曜日まで何日(/tools/days-until-weekday/)というツールがあり、曜日を選ぶだけで自動計算してくれますが、ロジックを理解しておくと応用が効きます。
基本式はこれです。
// targetDay, currentDay は 0〜6 で日曜始まり
const diff = (targetDay - currentDay + 7) % 7;
// diff が 0 のときどう扱うかは用途次第
// 「今日を含む」なら 0
// 「必ず次の該当曜日」なら 0 のときは 7 日後ここで引っかかりやすいのが「今日含む?含まない?」問題です。月曜にマネージャーから「次の金曜までに出して」と言われたとき、それは「今週の金曜」なのか「来週の金曜」なのか曖昧です。ツール側では「今日の曜日と一致する場合は 0 日と返す」か「7 日と返す」かをオプションで切り替えられるようにしておくと、ユーザーに優しい設計になります。
もう 1 つ頻出なのが「来週の月曜日の日付」です。単純に today + 7 ではダメで、「来週の最初の月曜」を出すには今日から数えて何日ずらせば良いか計算する必要があります。JavaScript で書くとこうなります。
function nextMonday(from = new Date()) {
const d = new Date(from);
const day = d.getDay(); // 0=日, 1=月, ...
const diff = (8 - day) % 7 || 7; // 月曜なら 7 日後
d.setDate(d.getDate() + diff);
d.setHours(0, 0, 0, 0);
return d;
}|| 7 でゼロを 7 に置き換えているのは、今日が月曜のときに diff = 0 にならないようにするためです。「今日を含めて良い」要件なら || 7 を外せば OK。境界条件はこのようにテストを書き分けると事故が減ります。
営業日カウント
「納期まで営業日で 5 日」「支払期日は請求書発行から営業日 30 日以内」など、営業日での日数計算は業務システムの定番要件です。基本は 土日を除外して数えるのですが、日本の業務で使うなら 祝日も除かないと使い物になりません。
日本の祝日判定は、JavaScript なら holiday-jp ライブラリ、Python なら jpholiday あたりが定番です。内閣府が公開している CSV を取り込んでいるため、毎年の更新もそこそこ追従してくれます。自前で祝日テーブルを持つのは避け、ライブラリに任せましょう。
// JavaScript: holiday-jp でその日が祝日か判定
import * as holiday_jp from 'holiday-jp';
holiday_jp.isHoliday(new Date('2026-05-05')); // true(こどもの日)
// Python: jpholiday で判定
import jpholiday
jpholiday.is_holiday(datetime.date(2026, 5, 5)) // True営業日のカウントは、素朴に 1 日ずつインクリメントしながら「土日・祝日ならスキップ」で十分ですが、件数が多い場合は 営業日テーブルを事前に生成して DB に持つ方式が高速です。バッチで「翌営業日」「3 営業日後」を高頻度に呼ぶシステムでは、この手法を検討してください。
Excel / Google Sheets で営業日を扱うなら NETWORKDAYS 関数が便利です。=NETWORKDAYS(開始日, 終了日, [祝日リスト]) のように第 3 引数に祝日の範囲を渡すと、土日に加えて祝日も除外した営業日数を返します。逆に「N 営業日後の日付」を求めるには WORKDAY 関数を使います。どちらも「日本の祝日リスト」を別シートに持っておく必要があり、そこだけは年 1 回メンテナンスしてください。
海外向けサービスでは注意点がいくつか増えます。まず、中東諸国では金曜・土曜が週末なので「土日除外」のロジックがそのまま通用しません。サウジアラビア・UAE などは 2022 年前後に週末を金土から土日に変更しましたが、地域によってまだ金土が週末のところもあります。国ごとに「週末曜日」を設定できる汎用実装にしておくのが理想です。
カレンダー表示形式
日付を「一覧」として見せるとき、カレンダーの描き方にもいくつか流派があります。ベンリーの カレンダー(/tools/calendar/)は、月カレンダー・年カレンダー・西暦 / 和暦を切り替えながら使えるシンプルなツールです。
- 月カレンダー:1 月を 6 × 7 のグリッドで表示する最も一般的な形式。Outlook や Google カレンダーの標準表示。
- 週カレンダー:1 週間を縦方向の時間軸で表示。1 日の予定密度が高い人向け。
- アジェンダ形式:予定のある日だけをリストで並べる。スマホで見やすい。
- 年カレンダー:12 か月を 1 ページに圧縮して俯瞰する形式。祝日や長期休暇の計画に便利。
日本で特有なのが 和暦と 六曜の表示ニーズです。和暦は令和 8 年(2026 年)のように元号 + 年で表す形式で、官公庁の書類や年賀状などでは今も現役です。JavaScript なら Intl.DateTimeFormat が標準で対応しています。
new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
era: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(new Date('2026-04-15'));
// → '令和8年4月15日'六曜(先勝・友引・先負・仏滅・大安・赤口)は結婚式や葬儀の日取りで参照される伝統的な暦日で、旧暦の月日から機械的に決まります。これは標準 API では扱えないので、ライブラリ(qreki など)か自前の計算式を使うことになります。使う頻度は高くありませんが、冠婚葬祭系のサービスでは必須の機能です。
海外向けのカレンダー UI でもう 1 つ重要なのが、週の始まりの曜日です。日本やアメリカは日曜始まりが主流ですが、ヨーロッパや ISO 8601 は月曜始まりで、中東では土曜始まりの地域もあります。i18n ライブラリが提供する「ロケールごとの firstDayOfWeek」を必ず参照しましょう。
時刻フォーマット一覧
時刻の表記ゆれは日付以上にカオスです。ベンリーの 時刻フォーマット(/tools/time-formats/)は、現在時刻を複数のフォーマットで同時に表示し、必要なものをワンクリックでコピーできるツールです。フォーマットの一覧を置いておきます。
| フォーマット | 例 | 使いどころ |
|---|---|---|
| 24 時間表記 | 2026-04-15 09:30:00 | 日本の業務全般。デフォルトはこれでよい |
| 12 時間表記(AM/PM) | 9:30 AM | 米英向けのユーザー表示 |
| ISO 8601(UTC) | 2026-04-15T00:30:00Z | API レスポンス、DB 保存 |
| ISO 8601(ミリ秒) | 2026-04-15T00:30:00.123Z | 高精度ログ、分散トレース |
| RFC 2822 / HTTP Date | Wed, 15 Apr 2026 00:30:00 GMT | HTTP ヘッダ、メールヘッダ |
| UNIX 秒 | 1776384000 | タイムスタンプ比較、キャッシュキー |
| UNIX ミリ秒 | 1776384000123 | JavaScript 内部、ログの並べ替え |
日本は 24 時間表記が圧倒的に主流なので、ユーザー向け UI は HH:mm(00:00〜23:59)をデフォルトにしておけば大外しはしません。対して海外向けは、アメリカや一部の英語圏で 12 時間表記(9:30 AM)のほうが自然です。ロケール対応は Intl.DateTimeFormat の timeStyle: 'short' に任せるのが最も少ない手間で済みます。
HTTP ヘッダの Date や Last-Modified、メールの Date ヘッダで使われているのが RFC 2822 / RFC 5322 形式です。Wed, 15 Apr 2026 00:30:00 GMT のように、曜日の英語 3 文字 + 日 + 月英語 3 文字 + 年 + 時刻 + タイムゾーン略号という構成で、ISO 8601 より古くからあるフォーマットです。自分でパースする必要が出た場合は new Date('Wed, 15 Apr 2026 00:30:00 GMT') で JavaScript が受け付けてくれます。
これからの選択肢として見逃せないのが JavaScript の Temporal API です。Temporal.Now.instant() で現在のインスタント(UTC ベースの絶対時刻)を取得したり、Temporal.ZonedDateTime でタイムゾーン付きの日時を不変オブジェクトとして扱えたりします。従来の Date オブジェクトに比べて設計がはるかにまともで、DST の罠や月末計算の事故が激減します。主要ブラウザで順次実装中なので、新規プロジェクトでは積極的に検討してよいでしょう。
4 ツールの使い分け
ベンリーには日付・時刻に関するツールが 4 つあります。どれをいつ使うか迷ったら、この表を参考にしてください。
| ツール | やりたいこと | 典型ユースケース |
|---|---|---|
| 世界時計 | 複数都市の現在時刻を一覧したい | 海外チームとのミーティング調整、渡航前の現地時刻確認 |
| カレンダー | 任意の月 / 年を表示したい | 来年の祝日を確認、和暦の変換、スケジュール計画 |
| 時刻フォーマット | 現在時刻を ISO / UNIX / RFC で欲しい | API テストのタイムスタンプ、ログの手書き、デバッグ |
| 曜日まで何日 | 「次の金曜まであと何日」を知りたい | レポート提出期限の逆算、定例ミーティングまでの残日数 |
個人的なおすすめの組み合わせ方は、世界時計 + 時刻フォーマットの併用です。海外の同僚と話すときに「今こちらは 9:30 JST、そちらは 17:30 PST ですよね」と伝えたい一方で、Slack のスレッドに貼るタイムスタンプは UTC の ISO 8601 にしておきたい、というシチュエーションが頻繁にあります。この 2 つを同時に開いておけば、現地時刻の確認と API 用タイムスタンプの取得が並行してできます。
スケジュール系の業務なら カレンダー + 曜日まで何日の組み合わせが強力です。カレンダーで祝日や連休を俯瞰しつつ、重要なマイルストーンまでの残り日数を曜日まで何日で即座に数える、というフローが自然にできます。
よくある質問
2024-01-01T00:00:00Z と 2024-01-01T00:00:00+09:00 の違いは?
前者は UTC で 2024 年 1 月 1 日の 0:00 を指しており、日本時刻(JST)では同日の 9:00 に相当します。後者は日本時刻で 0:00 を指しており、UTC では 前日の 2023 年 12 月 31 日 15:00 に相当します。同じ文字列に見えて 9 時間ずれた別の瞬間を指しているので、DB の比較クエリや API のリクエストでこの 2 つを混同すると「1 日ズレる」「大晦日と元日を間違える」という事故が起きます。ベストプラクティスは、サーバー間通信では常に UTC(末尾 Z)を使い、ユーザーへの表示のときだけロケールに合わせて変換することです。
DST で 1 時間消えた日にバグが出たらどう対応する?
まず、保存してある日時がローカル時刻だけなのか、タイムゾーン情報付きなのかを確認してください。ローカル時刻だけの場合は、切り替え日の 2:00〜3:00 に該当するデータが文字通り存在しない(=nullable にしないとレコード作成が失敗する)か、逆に 1:30 のような曖昧なデータが 2 件生まれる可能性があります。対処は、日時を保存する際に必ず UTC に変換して保存すること、および UI 表示時にタイムゾーンを明示して変換することです。既存データがすでにローカル時刻で保存されている場合は、切り替え日の 2 時間だけ手動でパッチを当てるか、アプリ側で「DST 切り替え日は例外扱い」する特別なロジックを入れる必要があります。根本治療のつもりでデータマイグレーションをかけたほうが、長期的には楽です。
2038 年問題は今でも問題?
主要 OS・DBMS・言語処理系は 64 bit 化済みなのでほぼ解消しています。Linux は 5.6 で time_t が 32 bit だった環境も 64 bit に揃い、Windows はそもそも 64 bit FILETIME を使っているため影響なし。MySQL の TIMESTAMP 型は依然として 32 bit 範囲(1970–2038)という制約が残っていますが、DATETIME 型を使えば 9999 年まで扱えます。現実的にまだ問題が残っているのは、① IoT / 組み込み機器の古いファームウェア、② .zip や .tar のタイムスタンプフィールドのような古いファイルフォーマット、③ レガシー金融システムの C プログラム、などです。新規開発では 64 bit の time_t(int64_t)を使うか、言語標準の日時型(Python の datetime、Java の Instant など)を使えば気にする必要はありません。
うるう年・うるう日の扱いは?
グレゴリオ暦のうるう年ルールは「4 で割れる年はうるう年、ただし 100 で割れる年は平年、ただし 400 で割れる年はうるう年」です。2000 年はうるう年、2100 年は平年。この判定を自前で書くのは 絶対にやめましょう。すべての言語に日付ライブラリがあり、Date 型が 2 月 29 日を正しく扱ってくれます。うるう日でバグが出るのは、だいたい「2 月 29 日生まれの人の年齢計算」「毎月 29 日が締め日の契約」「4 年に 1 回しか実行されないジョブ」の 3 パターンです。2 月 29 日生まれのユーザーを相手にするときは、平年の誕生日を 2 月 28 日に寄せるか、3 月 1 日に寄せるかの方針を決めてテストケースに含めてください。
「来週の月曜」を正確に出す方法は?
「今週の月曜」なのか「来週の月曜」なのかが曖昧なので、まず要件を固めましょう。一般的には「今日を基準に、カレンダー上で次に来る月曜」を指すことが多く、今日が日曜なら翌日、今日が月曜なら翌週の月曜、今日が火曜〜土曜ならその週の日曜を越えて月曜という計算になります。JavaScript での実装は本文 7 節の nextMonday() 関数を参考にしてください。要点は、(8 - day) % 7 || 7 の || 7 を忘れないこと。これを忘れると月曜に呼ばれたときに「今日」を返してしまい、ユーザーから「来週って言ったのに今日が返ってくる!」と苦情が来ます。境界値のテストケース(今日が月曜、今日が日曜、今日が土曜)は必ず書きましょう。
日付・時刻でサクッと困りごとを解決したいなら
ベンリーの世界時計・カレンダー・時刻フォーマット・曜日まで何日の 4 ツールは、ブラウザだけで完結する日付・時刻系ツール集です。インストール不要・ログイン不要で、いますぐ使えます。
世界時計を開く → カレンダーを開く → 時刻フォーマットを開く → 曜日まで何日を開く →