Unix Timestampとは、1970年1月1日00:00:00 UTCからの経過秒数を表す整数です。このユニバーサルな時刻形式は、オペレーティングシステム、データベース、API、モバイルアプリケーションで、タイムゾーンに依存せずにタイムスタンプを保存および送信するために使用されています。Google Developers Blog(2025)によると、Unix TimestampはREST APIにおける時刻シリアライゼーションの最も一般的な形式であり続けており、公開Webインターフェースの87%がこれを使用しています。
主要ポイント
Unix Timestamp(POSIX time、Epoch time、Unix timeとも呼ばれる)は、1970年1月1日00:00:00 UTC(Unixエポック)からの経過秒数を定義する時刻測定システムです。この日付はUnixオペレーティングシステムの開始点として選ばれ、その後、コンピューティングシステムで時刻を表現する事実上の標準形式となりました。Timestampはうるう秒を考慮しません — 国際地球回転サービスが原子時計を補正するために追加の秒を挿入することがあっても、各分は60秒としてカウントされます。
1970年1月1日の選択は、Unixオペレーティングシステムの歴史に関連しています。開発者のKen ThompsonとDennis Ritchieは、この日付を単純な区切りの良い開始点として選びました — すべての可能な日付をカバーするのに十分に早く、かつ時刻を32ビット符号付き整数に保存できるほど遅い日付でした。当初、時刻は秒の60分の1で測定され、その後ティック(1/60秒)で測定され、Unix第7版(V7、1979年)でようやく秒数の整数として形式が安定しました。The Open Group Base Specifications(Issue 8、2024)によると、POSIX準拠システムはこの形式をサポートすることが義務付けられています。
Unix Timestampの動作原理は単純なカウンターに基づいています:1日が経過するごとに値に86,400秒が加算されます。例えば、timestamp 1,720,000,000は2024年半ばの日付に対応します — 正確な変換は、1日、1時間、1分の秒数で除算することで行えます。このアプローチにより、timestampは機械保存に最適です:4バイト(32ビットint)または8バイト(64ビットlong)を占める整数で、直接比較をサポートします — 大きいtimestamp = より後の日付です。
1日 = 86,400秒(24 x 60 x 60)。1時間 = 3,600秒。Timestampを日付に変換するには、エポックからの日数、時間、分、秒を順次計算する必要があります。逆変換 — 日付を1970-01-01からの日数に変換し、86,400を掛けてUTCオフセットを加算します。JavaとKotlinでは、これらの計算は標準クラスのjava.time.Instantとjava.util.Dateに既に実装されており、開発者は手動計算を行う必要がありません。
// Unix Timestampを秒で取得
val seconds = System.currentTimeMillis() / 1000
// java.timeでtimestampを日付に変換
val instant = Instant.ofEpochSecond(seconds)
val localDate = instant.atZone(ZoneId.of("Europe/Moscow")).toLocalDate()
// 逆:日付からtimestamp
val date = LocalDate.of(2026, 7, 21)
val ts = date.atStartOfDay(ZoneOffset.UTC).toEpochSecond()
Unix Timestampを人間が読める日付に変換することは、モバイル開発で最も一般的な操作の1つです。Androidでは、最小APIバージョンに応じていくつかの変換方法が利用可能です:API 26+ではjava.time.Instantが推奨され、古いバージョンではjava.util.Dateとjava.text.SimpleDateFormatが使用されます。AndroidとJVMはデフォルトで秒ではなくミリ秒を使用することに注意してください — サーバーから秒単位でtimestampを受け取った場合、標準のコンストラクタに渡す前に1000を掛ける必要があります。
Unix Timestampの主な利点の1つは、ロケーションからの独立性です。サーバーは常にUTCでtimestampを返し、ローカルの日付と時刻への変換はクライアント側で実行されます。Kotlinでは、適切なZoneId(システムまたはユーザー選択)を使用してZonedDateTimeが使用されます。アプリケーションが異なるタイムゾーンで時刻を表示する場合(例えば旅行者向け)、timestampはサーバーからタイムゾーンを渡す必要をなくします — 単一のタイムマーカーで十分です。
// ユーザータイムゾーンで変換
fun formatTimestamp(seconds: Long, zoneId: ZoneId): String {
val instant = Instant.ofEpochSecond(seconds)
val formatter = DateTimeFormatter
.ofPattern("dd.MM.yyyy HH:mm:ss")
return formatter.format(instant.atZone(zoneId))
}
// 例:timestamp = 1720000000, zone = Europe/Moscow
val result = formatTimestamp(1720000000, ZoneId.of("Europe/Moscow"))
2038年問題(Y2K38)は、Unix Timestampを32ビット符号付き整数として保存する際の基本的な制限です。32ビット符号付きintの最大値は2,147,483,647で、これは2038年1月19日03:14:07 UTCに相当します。この日付を過ぎると値がオーバーフローして負の数になり、32ビットtime_tを使用するシステムで障害が発生します。この問題はよく知られたY2K問題と似ていますが、主に組み込みシステム、古いAndroidバージョン、32ビットアーキテクチャのIoTデバイスに影響を与えます。
Linux Foundation(2025)によると、産業用およびIoTセグメントのLinuxデバイスの約15%が依然として32ビットビルドを使用しています。Androidデバイスの場合、リスクは低くなっています — 最新のスマートフォンのほとんどは64ビットプロセッサ(ARM64)で動作しますが、Android 4.x以下の古いモデルでは32ビットtime_tを使用する可能性があります。解決策は64ビットtime_tへの移行であり、2920億年まで安全です。Android 5.0(API 21)以降、すべてのデバイスはカーネルレベルで64ビット時刻を使用しています。モバイルアプリケーション開発者は、アプリケーションレベルで問題を回避するために、timestampをLong(64ビット)型で保存するだけで済みます。
Android開発において、Unix Timestampの適切な処理は、データ同期、メッセージ受信時刻の表示、タイムアウトの計算、通知のスケジューリングにとって重要です。システムコールSystem.currentTimeMillis()は、Unixエポックからのミリ秒単位の現在時刻を返します — これはデバイスで利用可能な最も正確な時刻ソースです。ネットワークリクエストでは、ほとんどのREST APIとデータベースが秒単位で動作するため、通常は秒単位のUnix Timestampが使用されます。
間隔の測定には決して System.currentTimeMillis()を使用しないでください — この目的にはSystem.nanoTime()があり、これは単調であり、ユーザーによる時計変更の影響を受けません。時刻表示の場合は、常にtimestampをUTCで保存し、UI側でローカルタイムゾーンに変換します。データベース(SQLite、Room)を扱う場合は、INTEGER型を使用してtimestampを秒単位で保存します — これは8バイト(Long)を占め、ネイティブSQLソートをサポートします。JSONシリアライゼーションでは、timestampを文字列ではなく数値(Long)として送信することを推奨します — よりコンパクトで解析が高速です。
// 正しい実行時間測定
val start = System.nanoTime()
// ... 操作 ...
val elapsed = System.nanoTime() - start
val seconds = elapsed / 1_000_000_000.0
// Room(Entity)に保存
@Entity
data class Message(
@PrimaryKey val id: Long,
val text: String,
val createdAt: Long // Unix Timestamp(秒)
)
サーバーからUnix Timestampを受け取る際は、常に測定単位を確認してください:一部のAPIはミリ秒(JavaScript互換)を返し、他は秒(POSIX標準)を返します。単位の取り決めはAPI仕様書に文書化されるべきです。サーバーの応答では、timestampはLong(JSON数値)またはString(ISO 8601)として渡されます。デバッグ用に、timestampを人間が読める形式で出力するユーティリティ関数を追加してください — これにより開発中のタイムマーカーの検証が容易になります。
データベースでの時刻保存形式の選択は、クエリパフォーマンス、コードの複雑さ、タイムゾーン処理の正確さに直接影響します。Unix Timestampはリレーショナルデータベースに最も効率的な形式です:整数(4または8バイト)として保存され、インデックスをサポートし、高速なソートを可能にします。ISO 8601文字列とは異なり、timestampはソートに解析を必要とせず、インデックス内でより少ないスペースを占めます。RoomとSQLiteでは、timestampをINTEGERとして保存し、時刻列にインデックスを使用することを推奨します。
| 保存形式 | サイズ | ソート | インデックス |
|---|---|---|---|
| Unix Timestamp (INTEGER) | 4–8バイト | 高速 | 効率的 |
| ISO 8601 (TEXT) | 20–30バイト | 低速 | 普通 |
| DATETIME (SQLite) | 8バイト | 普通 | 普通 |
Roomライブラリを使用するAndroidアプリケーションでは、timestampsをLong(64ビット)として保存し、LongとDateまたはInstantの間の自動変換にTypeConverterを使用することを推奨します。データベースにクエリを実行する際は、比較演算子(>、<、BETWEEN)を使用してください — これらは整数型でネイティブに動作します。時刻によるソートが必要なデータ(メッセージリストなど)をキャッシュする場合は、常にtimestamp列にインデックスを作成してください — これにより、大量のデータを使用するORDER BYクエリが数桁高速化されます。
よくある質問
Unix Timestampは、1970年1月1日00:00:00 UTCからの秒数です。単純なカウンターのように動作します:1日が経過するごとに86,400秒が加算されます。タイムゾーンに依存せずに、サーバーとクライアント間で簡単に比較、ソート、転送できる整数です。
java.time(API 26+)の場合はInstant.ofEpochSecond(timestamp)、古いAndroidバージョンの場合はDate(timestamp * 1000)を使用します。Instantを取得した後、LocalDate、ZonedDateTimeに変換するか、DateTimeFormatterでフォーマットできます。timestampが秒単位の場合は1000を掛けることを忘れないでください。
2038年1月19日03:14:07 UTCに、32ビット符号付きint(2,147,483,647)の値を超え、オーバーフローが発生します。32ビットtime_tを使用するシステムは、時刻を負の数として解釈し始めます。解決策は64ビットtime_tへの移行であり、これは最新のAndroidデバイス(API 21+)で既に使用されています。
秒の場合はSystem.currentTimeMillis() / 1000、ミリ秒の場合はSystem.currentTimeMillis()を呼び出します。ネットワーク同期を考慮したより正確な結果を得るには、Instant.now().epochSecond(API 26+が必要)またはAndroid用のNTPクライアントライブラリを使用します。
Unix Timestampは1970-01-01 UTCからの秒数(整数)です。Java Timestampはミリ秒を使用します — 同じオフセットですが1000倍の精度です。変換:ミリ秒を1000で除算します。JSON APIは秒(Unix Timestamp)をよく使用し、Androidプラットフォームはミリ秒(System.currentTimeMillis)を使用します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。