UNIX 時刻 (UNIX タイム) は、1970 年 1 月 1 日 0 時 0 分 0 秒 (協定世界時、UTC) からの経過秒数で日時を表す方法です。PHP の time() など、多くの言語やデータベース、API で使われています。JavaScript でも同じ値を得たい場面はよくありますが、JavaScript の日時はミリ秒で数えるため、そのままでは 1,000 倍の値になります。ここでは、正しく秒を得る書き方と、よく見かける書き方の落とし穴を説明します。

秒で得るには Math.floor(Date.now() / 1000)

// 今の UNIX 時刻 (秒)
const now = Math.floor(Date.now() / 1000);

Date.now() は、1970 年 1 月 1 日 (UTC) からの経過ミリ秒を返します。これを 1,000 で割ると秒になりますが、小数が残るので Math.floor() で切り捨てます。

Date のオブジェクトがすでにあるなら、getTime() でミリ秒を取り出せます。

const date = new Date("2026-11-16T00:00:00+09:00");
const seconds = Math.floor(date.getTime() / 1000); // 1794754800

桁数を見ると、秒かミリ秒かの見当がつきます。今の日時なら、秒は 10 けた、ミリ秒は 13 けたです。API から受け取った値をそのまま new Date() に渡して 1970 年の日付になったら、秒とミリ秒を取り違えていないかを疑います。

ビット演算で切り捨てる書き方は 2038 年に壊れる

小数を切り捨てる短い書き方として、| 0 や ~~ が使われることがあります。

// 勧められない書き方
const now = (Date.now() / 1000) | 0;

ビット演算をすると、JavaScript は値をいったん 32 ビットの符号付き整数に変換します。32 ビットの符号付き整数で表せる最大の値は 2,147,483,647 です。UNIX 時刻がこの値を超えるのは、2038 年 1 月 19 日 3 時 14 分 7 秒 (UTC) の次の 1 秒です。それ以降は、値が負の数に変わってしまいます。

(2147483648.2) | 0;       // -2147483648 (壊れている)
Math.floor(2147483648.2); // 2147483648 (正しい)

これは、UNIX 時刻を 32 ビットの符号付き整数で記録するシステムで起きる「2038 年問題」と同じ境目です。JavaScript の数値そのものは、もっと大きな値も正しく扱えるので、Math.floor() を使えばこの問題は起きません。有効期限のように未来の日時を扱う処理では、2038 年より先の値が出てくることも十分ありえます。

また、1970 年より前の日時は負の値になります。Math.floor() と Math.trunc() (0 の方向へ切り捨て) では負の値の扱いが違うので、どちらを使うかを決めてそろえておきます。

UNIX 時刻はタイムゾーンに左右されない

UNIX 時刻は「UTC の基準の瞬間から何秒たったか」なので、同じ瞬間なら、日本でもほかの国でも同じ値になります。端末のタイムゾーンの設定によって Date.now() の値が変わることはありません。

タイムゾーンが関わるのは、日時を文字にして表示するときと、文字の日時を読み取るときです。表示するときは、toLocaleString() でタイムゾーンを指定できます。

const date = new Date(1794754800 * 1000);
date.toLocaleString("ja-JP", { timeZone: "Asia/Tokyo" }); // "2026/11/16 0:00:00"
date.toLocaleString("ja-JP", { timeZone: "UTC" });        // "2026/11/15 15:00:00"

文字の日時を読み取るときは、時差を書いておくのが確実です。"2026-11-16" のように日付だけの文字列は UTC として、"2026-11-16T00:00" のように時刻があって時差が無い文字列は、端末のタイムゾーンとして読まれます。同じ日付でも結果が変わるので、+09:00 や Z (UTC) を付けて書きます。

UNIX 時刻から日時に戻す

秒の UNIX 時刻を Date に戻すときは、1,000 を掛けてミリ秒にしてから渡します。

const seconds = 1700000000;
const date = new Date(seconds * 1000);
date.toISOString(); // "2023-11-14T22:13:20.000Z"

toISOString() は、UTC の日時を決まった形式の文字列で返すので、記録やデータの受け渡しに向いています。

なお、Date.now() は利用者の端末の時計をもとにしているため、端末の時計がずれていれば値もずれます。有効期限の確認のように、正確さが必要な処理では、サーバー側の時刻を使います。

まとめ

  • UNIX 時刻 (秒) は Math.floor(Date.now() / 1000) で得る。Date はミリ秒で数える
  • | 0 や ~~ での切り捨ては、32 ビットの範囲を超える 2038 年 1 月 19 日以降に壊れるので使わない
  • UNIX 時刻はタイムゾーンに依存しない。タイムゾーンが関わるのは表示と読み取りのとき
  • 日時に戻すときは new Date(秒 * 1000) と、ミリ秒にしてから渡す

参考