※購入先、ダウンロードへのリンクにはアフィリエイトタグが含まれており、それらの購入や会員の成約、ダウンロードなどからの収益化を行う場合があります。

現在時刻をミリ秒で取得する方法まとめ|UNIXミリ秒と表示の違いを目的別に整理

ログに「いつ起きたか」を正確に残したい、APIにミリ秒のタイムスタンプを付けて送りたい、処理時間をミリ秒単位で計測したい——。そんなときに「現在時刻 ミリ秒」と調べる方が最初につまずきやすいのが、ミリ秒の意味が用途によって変わる点です。
たとえば、UNIXエポックからのミリ秒(13桁のタイムスタンプ)が必要なのに、誤って0〜999のミリ秒部分を取得してしまうと、保存した値が時刻として成立せず、ログやDBが一気に崩れます。さらに計測用途では、現在時刻を返す仕組みと経過時間を測る仕組みを混同すると、結果が不自然に前後する原因にもなります。

本記事では、まず「ミリ秒」をUNIXミリ秒・ミリ秒部分・計測用タイムスタンプの3種類に整理したうえで、JavaScript・Python・Linuxそれぞれでの取得方法を目的別に詳しく解説します。加えて、“正確な現在時刻”が必要なケースで欠かせない時刻同期(NTP)の考え方や、Webのミリ秒時計の限界まで押さえ、実装と運用の両面で迷わない判断軸を提供します。読み終えたときには、あなたの目的に対して「何を使うべきか」「何に注意すべきか」が明確になります。

※本コンテンツは「記事制作ポリシー」に基づき、正確かつ信頼性の高い情報提供を心がけております。万が一、内容に誤りや誤解を招く表現がございましたら、お手数ですが「お問い合わせ」よりご一報ください。速やかに確認・修正いたします。

現在時刻のミリ秒で迷うポイント

現在時刻を「ミリ秒まで」扱いたい場面は、開発・運用・日常利用まで幅広く存在します。たとえば、Webアプリの操作ログに「いつクリックされたか」を残す、バックエンドが受け取ったイベントを時系列で並べ替える、外部APIにタイムスタンプを付けて送信する、バッチ処理の所要時間をミリ秒単位で測る、あるいは“ミリ秒表示の時計”で時刻を確認したい、といったケースです。

ところが「現在時刻 ミリ秒」という検索語には、複数の意味が混ざりやすいという落とし穴があります。具体的には、次の3つが同じ「ミリ秒」という言葉で語られます。

  • 1970年1月1日0時0分0秒(UTC)を起点にした「UNIXタイムスタンプのミリ秒」

  • ある時刻の末尾に付く「ミリ秒部分(0〜999)」

  • 経過時間計測に使う「高精度の計測用タイムスタンプ」

この違いを理解せずに実装すると、ログの桁が合わない、復元した日時が未来や過去に飛ぶ、計測値が不自然に前後する、といった問題が起きます。特に多言語(JavaScriptとPython、あるいはLinuxシェルなど)をまたぐシステムでは、言語ごとのAPI名が似ていても意味が違うため、混乱が増えがちです。

この記事では、まず「ミリ秒」の意味を整理し、そのうえでJavaScript・Python・Linuxでの取得方法を目的別に詳しく解説します。最後に、“正確な現在時刻”が必要な場面で欠かせない「時刻同期(NTP)」の考え方や、Web上のミリ秒時計を使うときの限界まで押さえます。読み終えたときに、「自分の目的ならどれを使うべきか」「何に注意すべきか」が迷わず判断できる状態を目指します。

ミリ秒の3種類:UNIXミリ秒/ミリ秒部分/計測タイムスタンプ

ここが最重要です。同じ「ミリ秒」でも、扱う対象が違えば、使うAPIも評価の仕方も変わります。

1) UNIXミリ秒(UNIXタイムスタンプのミリ秒)
これは「ある基準から何ミリ秒経過したか」という絶対的な時刻表現です。基準はUNIXエポック(1970-01-01 00:00:00 UTC)です。よくある特徴は次のとおりです。

  • 数値が大きい(2025年時点だと 13桁 が一般的)

  • 文字列化せずとも比較できる(大小比較で時系列が決まる)

  • 言語間・システム間でやり取りしやすい(JSONに数値で載せるなど)

これが欲しいのに、後述の「ミリ秒部分」を取ってしまうと、ログやDBが破綻します。

2) ミリ秒部分(0〜999)
これは「時刻の端数」で、HH:mm:ss.SSSSSS に相当します。単体では日時になりません。たとえば 123 という値だけでは「いつ」か分からず、時刻全体の補助情報として使います。表示整形・可読性向上が主用途です。

3) 計測用タイムスタンプ(高精度の経過時間)
これは「ある基点からの経過時間」を測るための値です。典型はブラウザの performance.now() のようなものです。UNIXエポックとは直接関係がない場合があり、「現在時刻(暦)」の表現には向きません。その代わり、処理時間を測るには有利です(時計の変更の影響を受けにくいなど)。

この3つを混同しないために、以降は「保存・送信(UNIXミリ秒)」「表示(ミリ秒部分)」「計測(計測用タイムスタンプ)」の順に、具体策を示します。

現在時刻のミリ秒とは何かを最初に整理する

実装例に入る前に、「ミリ秒」という言葉が招く典型的な誤解を整理します。ここが固まると、言語が変わってもブレにくくなります。

UNIXタイムスタンプのミリ秒とは

UNIXタイムスタンプは「秒」で語られることが多い一方、実装現場ではミリ秒が頻出します。理由は単純で、秒だと粒度が粗く、同一秒内に複数イベントが発生すると順序が曖昧になるからです。ミリ秒にしておくと、ほとんどのUI操作やAPIアクセス、ログ出力の分解能として十分な場面が多く、比較的扱いやすい桁数になります。

ここで重要なのは「単位が秒かミリ秒か」で、値の桁数と意味が変わることです。たとえば、1735000000 のような値は「秒」っぽく、1735000000123 のような値は「ミリ秒」っぽい、といった感覚が役に立ちます。ただし、将来年数が増えても桁数は変化し得るので、最終的には「単位を仕様として固定」することが大切です。

実務上のおすすめは次の方針です。

  • 外部とのやり取り(API、メッセージ、ログ基盤)で混乱を避けたいなら、UNIXミリ秒(整数)に統一

  • ISO8601(例:2025-12-24T12:34:56.789Z)のような文字列が必要な場合も、内部ではUNIXミリ秒を保持し、表示・出力で文字列化する

また、タイムゾーンをまたぐシステムでは、UNIXタイムスタンプはUTC基準のため、ローカルタイム表示と混ざらない利点があります。保存はUTC(UNIXミリ秒)、表示はローカル、という分離ができると、調査・分析・監査に強い設計になります。

ミリ秒部分0〜999とは

ミリ秒部分は「時刻の末尾」に付く端数です。12:34:56.789.789 がミリ秒部分です。ここで重要なのは、ミリ秒部分は繰り上がりがあることです。つまり、.999 の次の瞬間は次の秒へ移り、ミリ秒部分は .000 に戻ります。

この性質のため、ミリ秒部分だけを保存しても時系列比較はできません。「0〜999」という範囲は、あくまで“時刻の見た目”の一部です。ログの可読性を上げたり、同一秒内の差を見たりする用途には便利ですが、時刻の唯一性や比較を担保するには、UNIXミリ秒のような絶対表現が必要になります。

よくある失敗例は次のとおりです。

  • 「現在時刻のミリ秒が欲しい」→ getMilliseconds() を使った → 0〜999 しか取れず、ログが意味をなさない

  • 「タイムスタンプとしてミリ秒が欲しい」→ ミリ秒部分をDBに保存した → 同じ値が毎秒繰り返されて衝突する

表示目的ならミリ秒部分は正解ですが、保存・送信目的ならミリ秒部分は不正解になりがちです。目的を切り分けることが肝心です。

精度と正確さは別物

時刻には「精度(どこまで細かく扱えるか)」と「正確さ(真の時刻にどれだけ近いか)」という別軸があります。ミリ秒表示ができる=ミリ秒単位で正確、ではありません。

  • 精度:たとえば「ミリ秒まで表示できる」「マイクロ秒が取得できる」といった分解能

  • 正確さ:実際の標準時(または信頼できる参照時刻)からのズレの小ささ

正確さは、端末の時計がどの程度同期されているか(NTP設定やネットワーク状況)に依存します。逆に言えば、どれほど高精度なAPIで“細かい数字”が取れても、端末の時計そのものがズレていれば、その数字は「細かくズレている」だけになります。

開発での判断基準としては次が分かりやすいです。

  • 順序付け・相対比較が目的:UNIXミリ秒や、場合によっては計測用タイムスタンプで十分

  • 正確な絶対時刻が目的:端末の時刻同期(NTP)を含めた運用が必要

  • ベンチマーク・処理時間測定が目的:計測用タイムスタンプ(単調増加時計)を使う

以降は、具体的な取得方法を、目的別に詳しく解説します。

JavaScriptで現在時刻をミリ秒で取得する

JavaScriptはフロントエンドで最も頻出する言語のひとつで、ログ・API送信・計測・表示のすべてを担いがちです。ここでは、目的別に「何を使うべきか」「どういう落とし穴があるか」を丁寧に説明します。

UNIXミリ秒はDate.nowとgetTime

UNIXミリ秒(エポックからのミリ秒)が欲しいなら、JavaScriptでは次が定番です。

  • Date.now()

  • new Date().getTime()

どちらも「UNIXエポックからの経過ミリ秒」を返します。違いは、前者が静的メソッドで簡潔、後者はDateオブジェクトを経由するため、そのまま日時操作へつなげやすい、という程度です。

よくある用途別の使い方は次のとおりです。

ログに残す(機械処理用)
アプリ内のイベントを時系列で追うなら、数値のまま残すのが便利です。ソートや比較が容易で、パースコストも抑えられます。

const tsMs = Date.now();
console.log({ event: "click", tsMs });

APIへ送る(署名・リトライ制御など)
認証や署名で「リクエスト時刻」を送る仕様がある場合、ミリ秒で指定されることがあります。ここで秒とミリ秒を取り違えると、サーバ側で「時刻が不正(古すぎる/未来すぎる)」として弾かれることがあるため、要件を確認し、単位を固定して扱うことが重要です。

DB保存(多言語で共通化)
バックエンドがJavaやGo、Pythonであっても、UNIXミリ秒は互換性が高いため、フロントで採番して送る設計もあり得ます。ただし、改ざん耐性が必要ならサーバ側で採番する方が安全です(クライアント時刻は信用しない、という設計原則があるためです)。

ここでの注意点は「UNIXミリ秒=現在時刻の絶対表現」であることです。表示用のミリ秒部分とは別物です。

ミリ秒部分はgetMilliseconds

getMilliseconds() は「ミリ秒部分(0〜999)」を返します。つまり、.SSS に相当する端数です。これを使う目的は、主に次の2つです。

  • 可読ログとして HH:mm:ss.SSS の末尾を作りたい

  • UIにミリ秒まで表示したい(ストップウォッチのような見せ方)

例として、ユーザーの操作ログに可読形式を残す場合、次のように整形します。

const d = new Date();
const hh = String(d.getHours()).padStart(2, "0");
const mm = String(d.getMinutes()).padStart(2, "0");
const ss = String(d.getSeconds()).padStart(2, "0");
const ms = String(d.getMilliseconds()).padStart(3, "0");
const readable = `${hh}:${mm}:${ss}.${ms}`;
console.log(readable);

ここで大切なのは、可読形式は読みやすいが、機械処理の主キーにはしないという点です。可読形式はタイムゾーン依存(ローカル時刻)になりやすく、また文字列比較のルールを誤ると順序が崩れることがあります。機械処理はUNIXミリ秒、表示は可読形式、という二重化が安全です。

また、getMilliseconds() の値は 0〜999 の範囲で循環します。そのため、「ミリ秒だけ見たい」「ミリ秒の差だけで順序を判断したい」という設計には向きません。同一秒を跨げば意味が変わるためです。

計測はperformance.nowを使う

処理時間の測定(ベンチマーク、タイムアウト、レイテンシ計測)では、Date.now() より performance.now() が推奨される場面が多いです。理由は大きく2つあります。

  1. 単調増加であることが期待できる
    Date.now() は「暦の時刻」なので、NTP補正や手動変更で前後に動く可能性があります。計測の途中で時計が動くと、経過時間が負になったり、異常に大きくなったりする恐れがあります。計測用は「基点からの経過」を返す単調増加の仕組みが向いています。

  2. 高解像度である(小数を含む場合がある)
    performance.now() はミリ秒単位でも小数で返ることがあり、短い処理の差分を見やすくします。

計測の基本形は次のとおりです。

const start = performance.now();
// 何か処理
const elapsed = performance.now() - start;
console.log(elapsed);

ここでのポイントは、performance.now() は「現在時刻(暦)」ではないことです。ログに「何時何分何秒」として残したいなら Date が必要です。一方、計測値としてブレを減らしたいなら performance.now() が適しています。“時計”と“ストップウォッチ”は別物という感覚を持つと判断しやすくなります。

文字列でSSS表示する方法

ミリ秒表示をする要件は、ログ、UI、テスト出力などで多いです。表示整形には次の観点が重要です。

  • ゼロ埋め(7007 にする)

  • 24時間表記かどうか

  • タイムゾーン(ローカルかUTCか)

  • 日付も必要か(ログなら日時まで推奨)

例として、ログで扱いやすい YYYY-mm-dd HH:MM:SS.SSS を作る場合、次のように整形できます。

const d = new Date();
const yyyy = d.getFullYear();
const MM = String(d.getMonth() + 1).padStart(2, "0");
const dd = String(d.getDate()).padStart(2, "0");
const hh = String(d.getHours()).padStart(2, "0");
const mm = String(d.getMinutes()).padStart(2, "0");
const ss = String(d.getSeconds()).padStart(2, "0");
const ms = String(d.getMilliseconds()).padStart(3, "0");
console.log(`${yyyy}-${MM}-${dd} ${hh}:${mm}:${ss}.${ms}`);

さらに「UTCで統一したい」場合は、getUTCFullYear()getUTCHours() などUTC系メソッドへ切り替えます。保存・送信はUTC、画面はローカル、という方針があるなら、出力関数を分けておくと運用で迷いません。

Pythonで現在時刻をミリ秒で取得する

Pythonはバックエンドやスクリプトで使われることが多く、「保存・送信(UNIXミリ秒)」と「表示(整形)」の両方に出番があります。ここでは、よく使う実装パターンと、誤差・切り捨て・タイムゾーンの注意点を詳しく説明します。

UNIXミリ秒はtime系で取得する

PythonでUNIXミリ秒を得る最も分かりやすい方法は、time.time() をミリ秒へ変換することです。time.time() はUNIXエポックからの経過秒を浮動小数で返すため、* 1000 して整数化します。

import time
ts_ms = int(time.time() * 1000)
print(ts_ms)

ここでの論点は「丸めるか切り捨てるか」です。int() は切り捨て(床)になるため、厳密な丸めが必要なら round() を検討します。ただし多くのログ・イベント用途では「切り捨てでも問題にならない」ケースが多く、統一性の方が大事です。

また、より意図が明確な方法として、datetime から timestamp() を取り、それをミリ秒にする手もあります。タイムゾーンやUTCを明示したい場合は、日時型から変換する方が安心な場面もあります。

一方で、外部システムと単位を合わせるときは、必ず「ミリ秒か秒か」を仕様として固定し、命名で表現するのが有効です。たとえば ts_ms という変数名にする、DBカラム名を timestamp_ms にする、JSONフィールドを createdAtMs とする、といった工夫がミスを減らします。

表示用はdatetimeでミリ秒まで整形する

Pythonで表示用のミリ秒付き文字列を作る場合、datetime.now() を使い、isoformat(timespec="milliseconds") が便利です。ISO8601は多言語で扱いやすく、ログのパースもしやすい形式です。

from datetime import datetime
s = datetime.now().isoformat(timespec="milliseconds")
print(s)

ここで重要なのは、timespec="milliseconds"丸めではなく切り捨てである点です。たとえばマイクロ秒が 999999 のとき、ミリ秒に丸めると繰り上がりが起き得ますが、切り捨てなら繰り上がりません。どちらが正しいかは要件次第ですが、少なくとも「仕様として知っておく」ことが事故防止になります。

また、strftimeSSS を直接出すのが難しい環境もあるため、microsecond // 1000 でミリ秒を作り、ゼロ埋めして連結する方法が堅実です。

from datetime import datetime
dt = datetime.now()
ms = dt.microsecond // 1000
print(dt.strftime("%Y-%m-%d %H:%M:%S.") + f"{ms:03d}")

ログの可読性を上げたいだけなら、これで十分です。さらに、JSONログなど構造化ログであれば、可読文字列とUNIXミリ秒を両方持たせると、調査が速くなります。

タイムゾーンとUTCの扱い

時刻のトラブルで多いのは、ミリ秒そのものよりも、タイムゾーンの混在です。特に次の状況で混乱が起きます。

  • サーバはUTC、クライアントはローカル(JSTなど)

  • ログ基盤がUTCで集約するが、アプリログがローカル

  • 夏時間がある地域のログが混在する

この問題に対しては、基本方針を決めるのが最も効果的です。

  • 保存・集約・送信はUTCに統一

  • 表示(ユーザー向け)はローカルタイムゾーンで整形

Python側でUTCを明示するなら、タイムゾーン付きdatetime(aware datetime)を使い、UTCを指定します。これにより、「ローカルかUTCか分からない」という曖昧さを排除できます。実装では、標準ライブラリの datetimetimezone.utc を使う方法が分かりやすいです。

さらに、外部APIや他言語と合わせるなら、ISO8601の末尾に Z(UTC)を付ける形式や、UNIXミリ秒で統一する形式が多いです。どちらを採用するにしても、「仕様化」と「命名による明示」が重要です。

Linuxで現在時刻をミリ秒表示する

Linuxでは、ログの前処理や運用スクリプト、障害調査のワンライナーで「ミリ秒を付けたい」という要望がよく出ます。ここでは date を中心に、GNU環境と環境差の回避策を詳しく説明します。

GNU dateでSSSを出す

GNU coreutils の date コマンドは、フォーマット指定でナノ秒まで扱える(環境によって精度は変わる)ため、ミリ秒は %3N のように取得するのが定番です。たとえば、次の形式はログで非常に使いやすいです。

date '+%Y-%m-%d %H:%M:%S.%3N'

この出力は、目視でも差が分かりやすく、時系列の並びも崩れにくい形式です。さらに、UTCで統一したい場合は -u を付けます。

date -u '+%Y-%m-%d %H:%M:%S.%3N'

ただし、ここで注意したいのは「表示できる=その精度で正確」という意味ではない点です。OSの時計や取得機構の都合で、下位桁が常に 000 に近い、あるいは飛び飛びになるなど、実効精度は環境に左右されます。ログの可読用途なら問題にならないことが多い一方、ミリ秒単位で厳密な評価が必要な計測では、別の仕組みを使うべきです。

macOSなど環境差の回避策

Linuxの date を前提にしたスクリプトは、macOS(BSD date)などで動かないことがあります。%N が使えない環境があるためです。チームやCI環境でOSが混在する場合、次の戦略が有効です。

  • 実行環境を固定する:Dockerコンテナ内でGNU coreutilsの date を使う

  • アプリ側で時刻を出す:Python/Node/Goなどで整形してログへ出す

  • ログ基盤で時刻付与:収集エージェント(Fluent Bitなど)でタイムスタンプを付ける

シェルで無理に揃えようとすると、環境差で壊れやすくなります。運用上の強さを考えると、アプリ側またはログ基盤側で統一するのが安定です。

どうしてもシェルだけで「どこでも動く」を優先したい場合は、ミリ秒を諦めて秒で統一する、あるいはPythonを呼び出してミリ秒表示に寄せる、といった妥協策も現実的です。要件が「ミリ秒が必須」なのか「秒でも許容」なのかで判断が変わります。

ログで崩れないフォーマット例

ログで時刻を扱うときは、調査のしやすさを優先したフォーマットが重要です。おすすめは次の2軸で考えることです。

  • 人が読むYYYY-mm-dd HH:MM:SS.SSS

  • 機械が処理する:UNIXミリ秒(整数)

この2つを併用すると、次のメリットがあります。

  • 目視で時間差が掴みやすい(可読)

  • ソート・集計・結合が速い(機械処理)

  • タイムゾーンの混乱を避けやすい(UNIXミリ秒はUTC基準)

たとえば、アプリログに可読形式を入れ、構造化ログのフィールドにUNIXミリ秒を入れる設計は非常に強力です。障害調査では、検索・フィルタ・時系列整列の速度が変わります。

正確な現在時刻が必要なときの注意点

ここからは「現在時刻をミリ秒で表示したい」という要望の中でも、特に“正確さ”が重要な場合(監査、チケット、締切、取引、分散システムの整合)に関係する話をします。ミリ秒の取得方法を知っていても、端末の時計がズレていれば、出力の意味が薄れます。

端末時計がズレる理由と影響

端末時計がズレる理由は複数あります。代表的なものを挙げます。

  • NTPが無効、あるいは同期が不安定

  • 仮想化環境やコンテナでの時刻管理の影響

  • スリープ復帰や負荷状況による補正の揺れ

  • ユーザーや運用者が手動で時計を変更

  • ネットワーク遅延・経路の非対称性(同期精度の限界)

このズレは、ログ分析や障害調査に直結します。たとえば、複数サーバのログを突き合わせるとき、時刻が1〜2秒ズレているだけでも相関を追いにくくなります。ミリ秒単位で原因を追うなら、なおさらです。

また、クライアント(ブラウザ)時刻は特に信用しにくい場面があります。ユーザー端末はNTP設定が不明で、時計が大きくズレていることもあります。重要な記録(監査ログ、取引時刻など)は、サーバ側で採番する方が堅牢です。

NTPで時刻同期する考え方

“正確な現在時刻”が必要なら、NTP(Network Time Protocol)での時刻同期が基本になります。ここで重要なのは、NTPは「絶対に誤差ゼロにする魔法」ではなく、「現実的な範囲でズレを小さくし、継続的に補正する仕組み」だという点です。

運用上の観点では、次を押さえると理解が整理されます。

  • 同期元の信頼性:公的機関や信頼できるNTPサーバを参照する

  • ネットワーク品質:遅延やジッタが大きいと同期精度は下がる

  • 監視:同期状態(オフセットや同期中か)を監視し、ズレが大きい場合はアラートを上げる

  • 重要ログはサーバ採番:クライアント時刻ではなく、同期済みサーバ時刻で記録する

日本国内で「日本標準時に近い参照」を意識するなら、NICTなど公的な公開NTPの考え方を理解しておくと判断材料になります。最終的には、自社の要件(許容誤差、監査要件、運用コスト)に合わせて設計します。

Webのミリ秒時計を使うときの限界

Web上のミリ秒時計は、手軽に「ミリ秒まで表示」してくれるため便利です。しかし、ここでも「表示が細かい=正確」という誤解が起きがちです。Web時計は、次の要因で誤差が生じ得ます。

  • 通信遅延(ダウンロードや描画タイミング)

  • サーバ時刻との差(サーバも同期状態が不明な場合がある)

  • クライアント側の描画間隔(タイマーの精度や負荷)

  • ネットワークの非対称遅延(往復遅延の半分補正の限界)

そのため、Webのミリ秒時計は「目安」として使い、厳密な用途(締切や取引)では、公式に提示される時刻や、同期済み端末・サーバ時刻を優先するのが安全です。

もし「ミリ秒単位で厳密な同期」がビジネス要件として必要なら、次の優先順位で考えると整理しやすいです。

  1. 端末・サーバの時計をNTPで同期し、同期状態を監視する

  2. 計測や遅延評価は単調増加時計(計測用タイムスタンプ)で扱う

  3. 表示は可読性目的と割り切り、誤差の可能性を前提にする

よくある質問

ここでは、実装や運用で頻出するつまずきをQ&A形式で整理します。

UNIXミリ秒とミリ秒部分を取り違えたときの症状

最も多いのは、次の2パターンです。

症状1:時刻が復元できない(あるいは毎秒同じ値が繰り返される)
原因:UNIXミリ秒のつもりで、ミリ秒部分(0〜999)を保存した
結果:0〜999しかないため、同じ値が毎秒繰り返され、時系列に意味がなくなる

症状2:日時が極端に未来/過去へ飛ぶ
原因:UNIX秒のつもりでUNIXミリ秒(13桁)を秒として扱った
結果:秒として解釈すると値が大きすぎて、日時が異常になる

対策としては、「フィールド名に単位を入れる」「桁数チェックをテストに入れる」「受信側で単位を検証する」などが有効です。特にAPIでは、入力値の妥当性(範囲や桁)をバリデーションしておくと事故を防げます。

計測にDate.nowを使ってはいけないのか

「絶対にダメ」というより、「要件によっては問題が出る」という理解が適切です。

  • 短時間の簡易計測で、時計変更が起きない前提なら Date.now() でも動く

  • ただし、NTP補正や手動変更、サスペンド復帰の影響で、経過時間が不自然になる可能性がある

  • より安全に計測するなら、計測用タイムスタンプ(例:performance.now())を使う方がよい

つまり、「現在時刻(暦)」を扱いたいなら Date.now()、「経過時間(ストップウォッチ)」を扱いたいなら performance.now()、という切り分けが基本です。設計段階で用途を明示すると、実装者が変わっても判断がぶれにくくなります。

ミリ秒が000になりやすいのはなぜ

ミリ秒が 000 になりやすいと感じるとき、原因は主に次のいずれかです。

  • 取得元の実効精度が低い:OSや環境の時計更新間隔が粗い、あるいは取得APIが粗い

  • 丸めや切り捨て:ミリ秒へ落とす際の切り捨てで 000 に偏ることがある

  • 表示側の更新間隔:画面表示が60fpsや一定間隔で更新され、偶然 000 に当たりやすく見える

  • そもそも秒を見ている:整形やパースの過程でミリ秒を落としている

対策としては、「本当にミリ秒が取得できているか」をログで確認し、値の連続性や更新間隔を観察することです。ブラウザの表示だけで判断すると、描画やタイマーの都合で誤解が起きることがあります。

まとめ:目的別チェックリスト

最後に、実装時に迷わないための「目的別まとめ」と「確認項目」を提示します。ここまでの内容を凝縮し、現場で使える形にします。

目的別の最適手段比較表

目的 JavaScript Python Linux
保存・送信(UNIXミリ秒) Date.now() / new Date().getTime() int(time.time() * 1000) アプリ側で出力が安定(シェル依存を避ける)
表示(HH:mm:ss.SSS) getMilliseconds()SSS、ゼロ埋め datetime.now()+ミリ秒整形(microsecond//1000 など) GNUなら date '+%Y-%m-%d %H:%M:%S.%3N'
経過時間計測 performance.now() の差分 要件に応じて単調増加時計の利用を検討 計測専用の仕組み(言語/ツール)を検討

この表の読み方は、「何を得たいか」を最初に決め、該当する列の方法を選ぶ、というものです。特に「保存・送信」と「表示」を混ぜないのが最大のポイントです。

実装前チェックリスト

実装や運用の前に、次の項目を確認すると事故を大きく減らせます。

  • 目的の確認:欲しいのはUNIXミリ秒か、ミリ秒部分か、計測値か

  • 単位の固定:秒かミリ秒かを仕様として決め、フィールド名にも反映したか

  • タイムゾーン方針:保存はUTC、表示はローカル、などのルールを決めたか

  • 計測の手段:経過時間計測に暦の時刻(Date.now())を使っていないか

  • 環境差date %3N などGNU依存のコマンドを、混在環境で使っていないか

  • 正確さが必要か:監査・取引・厳密な締切なら、端末・サーバのNTP同期や監視が必要か

「現在時刻をミリ秒で取得する」は一見単純ですが、目的を切り分けるだけで選ぶべき手段が変わります。保存・送信はUNIXミリ秒、表示はミリ秒部分、計測は計測用タイムスタンプ、という整理を基準にすれば、多言語・多環境でもぶれずに実装できます。さらに、正確さが重要な場面では、時刻同期(NTP)という前提を忘れず、運用とセットで考えることが重要です。