世界を動かす技術を、日本語で。

プログラミングにおける時間の考え方

2025年6月25日原文(shanrauf.com)

概要

  • 時刻処理は ソフトウェア開発 に不可欠だが、複雑さゆえに多くのプログラマーが苦手意識
  • 時刻の本質的な理解には「 持続時間(duration)」と「 瞬間(instant)」の区別が重要
  • 絶対時刻 はエポック(基準点)からの経過秒数として表現可能
  • グレゴリオ暦・UTC・タイムゾーン の仕組みや調整(うるう秒含む)が現代の時刻管理を支える
  • 精密な時刻計算ではうるう秒や各地域の標準時ルールの考慮が不可欠

プログラミングにおける時間の概念モデル

  • 時刻処理 は多くのソフトウェアで不可欠だが、複雑なタイムゾーンやうるう秒のために誤解やバグの温床
  • 「UTCを使えばよい」という単純なアドバイス は、ユーザー向け日時表示や精密な計時には不十分
  • 時間には「 持続時間(duration)」と「 瞬間(instant)」という2つの重要な概念
    • 持続時間:例)Usain Boltの100m走にかかった秒数
    • 瞬間:例)ゴールした瞬間やレースの途中の任意の時点
  • 絶対時刻(absolute time) は、カレンダーやタイムゾーンとは独立した一意の瞬間を指す
  • 瞬間同士の順序や間隔を正確に表すには、「 エポック(epoch)」という基準点からの経過時間で管理
    • 例:Unixエポック(1970年1月1日00:00:00 UTC)からの秒数
    • 他にもJaiのApollo_Timeなど独自エポックも存在

エポックと絶対時刻の表現

  • エポック は任意の瞬間を0秒と定義し、以降の時刻をそこからの経過秒数で表現
  • Unix timeはUnixエポックを基準にし、32ビット整数で1970〜2038年を効率的に表現可能
  • 日常会話でも「昨夜」「明日の正午」など、無意識に現在時刻を基準点として利用

グレゴリオ暦と市民時間

  • 人間は「 市民時間(civil time)」としてグレゴリオ暦を使い、年/月/日/時/分/秒で時刻を表現
  • ロケールによる表示形式の違い(例:en-US 6/5/2025 6:00 PM vs de-DE 5.6.2025, 18:00)があるが、指す瞬間は同じ
  • 期間(period) は曖昧な持続時間(例:1ヶ月=28〜31日)であるため、計算時に注意が必要

カレンダーとエポックの相互変換

  • Unix timeとグレゴリオ暦は、異なるエポックを持つ「秒数基準」表現であり、相互変換が可能
  • エポックの選択は、システム要件や表現範囲、リソース効率に応じて柔軟に行う

時刻の基準と人類の時間管理

  • 古くは太陽や地球の自転・公転を基準に1日24時間・1年365日を定義
  • 1秒=1太陽日の1/86400としたが、地球の自転は年々遅くなっており、厳密には不正確
  • うるう年で公転周期(約365.25日)に対応するが、自転速度の変化には非対応

UTCとうるう秒

  • UTC(協定世界時) は、原子時計を基準にした国際標準時
  • 1秒=セシウム133原子の放射周期9,192,631,770回分(SI秒)で厳密に定義
  • 世界中の原子時計の平均値をIERSが管理し、NTPサーバーを通じて各コンピュータに配信
  • 地球の自転とのズレを補正するため「 うるう秒(leap second)」を不定期に挿入・削除
    • 例:23:59:59の次に23:59:60(正のうるう秒)、または23:59:58→00:00:00(負のうるう秒)
    • 1972年以降、27回追加(削除は未実施)
    • うるう秒の調整は突発的で予測困難、今後2035年に廃止予定

うるう秒と精密な時刻計算

  • うるう秒の存在により、1日は必ずしも86,400秒ではなく、86,401秒や86,399秒の場合も
  • 日付間の正確な持続時間計算には「うるう秒の総和」を加減する必要
  • うるう秒はIERSが事前に告知し、各システムがデータを更新して対応

プログラムとうるう秒の対応例

  • JavaScriptのDateオブジェクト(Unix timeベース)はうるう秒を考慮しないため、「真のUTC」ではない
  • Date.now()の返すミリ秒数は、実際の経過時間より少なくなる場合がある

タイムゾーンと標準時

  • UTCは絶対時刻を提供するが、世界各地で太陽の位置が異なるため「 タイムゾーン」が必要
  • タイムゾーンは各地域の「標準時(standard time)」のルールを定め、UTCからのオフセットで表現
    • 例:日本標準時(JST)はUTC+9、Line IslandsにはUTC+14も存在
  • 同じ瞬間でも、タイムゾーンによって表示される日時が異なる

まとめ

  • 時刻管理の本質 は、「持続時間」と「瞬間」、「エポック基準の表現」、「うるう秒やタイムゾーンの考慮」
  • 精密な時刻計算やユーザー向け表示には、 カレンダー・UTC・タイムゾーンの仕組み を正確に理解・実装する必要
  • システム要件に応じて適切な時刻表現・計算方法を選択することが、バグや混乱を防ぐ鍵

Hackerたちの意見

OPが夏時間の悪夢について話してくれて嬉しい!でも、毎年の天気チャートを重ねるとき、4年ごとにグラフが1日ずれて1/366の幅になっちゃって、月の区切りがぴったり合わないのが嫌なんだよね。それか、2月28日を重複させないと線が途切れちゃうし。どうやって表現するかまだ決めてないけど、ほんとイライラする。

いい投稿だね。時間のこと、いつも考えちゃうよ(笑)。君が楽しめそうな別の情報源があるよ(NTPと同期の質問について)TigerBeetleからの「Implementing Time」だよ:Implementing Time

(投稿者)リンクありがとう!

他のエポックも使えるよ(例:JaiのApollo_Timeは、1969年7月20日20:17:40 UTCのアポロ11号の着陸を使ってる)。他にもヴァーナー・ヴィンジのファンがいるね。でも、エポックとしてはちょっと変わった選択だよね。だって、システムとのインターフェースを考えると、そのエポックが始まるのは大体5ヶ月後なんだから。

ソフトウェア考古学のポイントって、そういうことだよね?最初の数百年では明らかだったことが、後になっては理由がわからなくなることもあるし、5ヶ月なんてどうでもいいじゃん。ロゼッタストーンでもないと、時間がずれてるかどうかすら確信できないし、歴史家が説明できない数ヶ月が出てくるかもしれないよ。

時間ってほんとに混乱してるよね。常に。著者は問題の表面をちょっと触れただけだし。GPS/GNSS衛星に影響を与える相対性理論の時間の遅れを除いても、やっぱり混乱してる。タイムゾーンはもちろんだけど、タイムゾーンが使われる前はどうだったの?途中で、どのタイムゾーンを使うかも問題だよね。ケーニヒスベルクはドイツの時はCETだったけど、ロシアになったらEETに変わったし。15分ずれてる国もあるし、夏時間の話はもうやめておこう。レバノンでは、DSTが同時に使われていたこともあったし、予約を取るのが大変だよ…。ユリウス暦からグレゴリオ暦への移行も、何年もかけて行われたし、国境によっても違ったりして…。特定の年にうるう日を入れ忘れた国もあって、数年間3月1日が全然違う日になったこともあった。時間ってほんとに混乱してる。今も、これからもずっと。

著者はIANAがケーニヒスベルクをどう扱うかを説明してるけど、論理的には独自のタイムゾーンだね。IANAのタイムゾーンは、現在のルールと将来のルールを共有する地域のセットを指すだけじゃなく、1970年1月1日00:00+0以降の民間時間の歴史も共有してるんだ。つまり、この定義はどの地域が単一のIANAタイムゾーンにまとめられるかについて、より制限的なんだよね。1970年以降に民間時間のルールを変更した地域は、他の地域と一緒にまとめることができないから。時間が混乱してるのには同意するよ。それに、15分のずれは狂ってるし、なんで誰かがそれを使ってるのか理解できない。

そうだね。幸いなことに、多くのアプリはローカルの民間時間とOSで設定されたタイムゾーンだけでやっていけるよね。うるう秒とか気にすることはあまりないし、多くのアプリはミリ秒の精度とかも気にしない。もし君のアプリがそれらを気にするなら、すぐに混乱しちゃうよ。

そうなんだ、いくつかのタイムゾーンでは、1時間の差だけじゃなくて、30分や45分の差もあるんだよ。インドはUTC +5:30、ロードハウ島はUTC +10:30 / +11:00、ニュージーランドのチャタム諸島はUTC +12:45 / +13:45、イランはUTC +3:30 / +4:30とかね。X / Yの形式では、Xが標準時間で、Yが夏時間を意味するんだ。ややこしいよね。完全なリストはここにあると思うよ。https://www.timeanddate.com/time/time-zones-interesting.html Bashスクリプトを使えば、/usr/share/zoneinfo/のファイルを基にした詳細なリストが得られるよ。つまり、整数以外の時間オフセットを持つタイムゾーンを見つけられるんだ。

さらに悪いことに、宗教によってタイムゾーンが変わる地域もあるんだ。レバノンでは「イスラム時間」と「キリスト教時間」があった時期があったよ(今もそうなのかは不明だけど)。

一番ひどいのは多分モロッコの夏時間だね。計算するのはソフトウェアじゃ無理だと思う。月の見え方を正確に知るには、正確な場所を把握して、山が視界を遮ってないか確認しないといけないと思う。

あまり触れられてない2つのことがあるんだ:- システムクロックのドリフト。Googleのインスタンスはデータセンターで原子時計を使って正確な時間を保ってるし、うるう秒を1日で分散させてる。正確な時間の測定には重要かもしれない。- 時間情報がどう消費されるかを考えてみて。写真共有サイトなら、各写真に必要なのは場所とローカルの日付と時間だよね。だから、これが欠けてても、大晦日の写真はタイムゾーンや場所を考慮しなくてもほぼ真夜中になる。実際にそういうケースがあって、自動で調整されない文字列表現を選んだんだ。視聴者のローカル時間に変換するのはあまり役に立たない。

Hacker Newsで議論の続きを見る