記事
Unixタイムスタンプとcron式の解説
Unixタイムスタンプは単なる整数です。cron式は単なる5つのフィールドです。どちらもバックエンドの作業で頻繁に登場し、どちらも予測可能な形で混乱を引き起こします。一方はタイムゾーンが原因で、もう一方は単位が原因です。
Unixタイムスタンプとは何か
Unixタイムスタンプは1970-01-01 00:00:00 UTC(Unixエポックとして知られる基準点)からの経過秒数を数えます。この定義には2つの重要な含意があります。第1に、カウントはUTCで行われます。数値自体にタイムゾーンは埋め込まれていません。1718400000は、それを格納しているマシンがどこにあるかに関わらず、地球上どこでも同じ瞬間を意味します。第2に、エポックは秒単位で定義されており、他の単位ではありません。1718400000のような値は、システムまたはプロトコルが明示的に別の選択をしていない限り、常に1970年1月1日UTC深夜0時からの秒数です。タイムスタンプは設計上タイムゾーンフリーであり、異なる地域の時計が同じ瞬間を曖昧さなく参照する必要があるログ・データベース・システム間通信において有用です。

秒・ミリ秒・2038年問題
多くの現代のランタイムとAPIは秒ではなくミリ秒を使用します。JavaScriptのDate.now()はミリ秒を返すため、1718400000000は秒精度の値1718400000と同じ瞬間です。未知のタイムスタンプを受け取ったとき、桁数が単位を教えてくれます。10桁の数値はほぼ必ず秒で、13桁の数値はほぼ必ずミリ秒です。2038年問題は別の選択肢、つまり秒精度のタイムスタンプを符号付き32ビット整数に格納することから生じます。符号付き32ビット整数の最大値は2147483647で、2038-01-19 03:14:07 UTCに相当します。その秒が過ぎると、この境界を処理しないシステムではカウンターが大きな負の数にオーバーフローし、日付が1901年に戻ります。修正策は64ビットストレージを使用することです。現在のほとんどのオペレーティングシステムとデータベースはすでにそうしていますが、数十年前にフィールド幅を固定した組み込みシステム・ネットワークデバイス・古いファイルフォーマットはリスクが残っています。
エポックを人間が読める日付に変換する:タイムゾーンのステップ
エポック値を読みやすい日付に変換するには2つのステップが必要です。整数からUTCの日付コンポーネントを取得し、UTCオフセットを適用して現地時刻を求めます。タイムスタンプ自体はUTCです。1718325000が表す日付を尋ねると、正しい答えはUTCで2024-06-14の00:30です。夏のニューヨーク(UTC-4)では、同じ秒は前日である2024-06-13の20:30に当たります。時刻だけでなく日付そのものが変わります。このステップを省略すると誤った結果が生まれます。開発者がタイムスタンプをUTCでログに記録し、レポートツールが変換せずに現地時刻でレンダリングすると、日付が数時間または丸1日ずれているように見えます。Sunastyのタイムスタンプコンバータツールはこれを明確に処理します。エポック値を入力すると、UTCの日付と時刻がデバイス自身の現地の日付と時刻と並べて表示されるため、今回のような日付の境界越えも一目で分かります。変換はブラウザ上で実行され、貼り付けた値はどこにも送信されません。

cron式:5つのフィールド・範囲・ステップ・リスト
cron式はUnix系システムで繰り返しジョブをスケジュールします。標準構文はスペースで区切られた5つのフィールドです。分(0-59)・時(0-23)・日(1-31)・月(1-12)・曜日(0-7、0と7はどちらも日曜日を表します)。フィールドのアスタリスク(*)は「すべての有効な値」を意味します。「30 8 * * 1-5」という式は月曜日から金曜日の08:30に実行されます。範囲はハイフンを使います。「1-5」は値1・2・3・4・5をカバーします。リストはカンマを使います。「1,15」は1日と15日を意味します。ステップはスラッシュを使います。分フィールドの「*/15」は15分ごと(0・15・30・45)を意味します。これらの組み合わせを一緒に使えます。「0-30/10」は0・10・20・30を意味します。cronにはタイムゾーンフィールドがありません。デーモンは実行しているマシンの時計を読み、そのサーバーの現地タイムゾーンに設定されています。サーバーがUTCで動作しているのに開発者が現地時刻を期待すると、スケジュールは間違った時刻に実行されます。実用的なルールはcronスケジュールをサーバーの現地時刻の式として扱い、cron行と合わせてサーバーのタイムゾーンを文書化することです。
タイムスタンプコンバータをローカルで使用する
Sunastyのタイムスタンプコンバータは双方向に変換します。エポックから人間が読める日付へ、そして人間が読める日付からエポックへ。秒精度の値またはミリ秒精度の値を入力でき、ツールは桁数から単位を検出します。結果はUTCとデバイス自身の現地タイムゾーンを並べて表示し、コピーしやすい秒とミリ秒の生の値も併記します。「Now」ボタンをクリックすれば現在のタイムスタンプが即座に入力され、ターミナルを開かずに現在のUnix時刻を確認できます。個別のタイムゾーン選択はありません。現地列は常にブラウザに現在設定されているタイムゾーンを反映します。これらすべてがブラウザ上で動作します。フィールドに貼り付けた値はクライアントサイドのJavaScriptで読み取られ、デバイスを離れることはありません。
この記事で紹介するツール
よくある質問
JavaScriptはなぜ秒ではなくミリ秒を使うのですか?
JavaScriptのDateオブジェクトはサブ秒精度を持つように最初から設計されており、ミリ秒は小数点を必要とせずに秒の1000倍の解像度を提供します。トレードオフとして値が大きくなります。Date.now()が13桁の数値を返す一方、ほとんどのサーバーサイドのタイムスタンプが10桁なのはそのためです。
cronを実行するすべてのサーバーはUTCである必要がありますか?
いいえ。しかしサーバーをUTCで動かすことは一般的な慣行です。曖昧さが取り除かれるからです。サーバーがUTCにある場合、「0 2 * * *」というcron式は02:00 UTCを意味し、その時刻は年間を通じて安定しています。夏時間を観測するゾーンのサーバーでは、同じジョブが夏と冬で異なるUTCの瞬間に実行され、時計変更の境界で2回実行されたりスキップされたりする可能性があります。
2038年以降のタイムスタンプに安全なストレージタイプは何ですか?
符号付き64ビット整数は秒精度のタイムスタンプを292277026596年まで保持でき、実用上の懸念を大幅に超えます。現在のほとんどのデータベースはデフォルトで64ビット値としてタイムスタンプを格納します。32ビットフィールドを使用するレガシースキーマまたはバイナリファイルフォーマットを扱っている場合、2038年の境界前に64ビットストレージに移行することが正しい対処法です。