Guide

エポックタイムの説明

はじめに

エポック タイム (Unix タイムスタンプまたは POSIX タイムとも呼ばれます) は、特定の基準日時に経過した秒数として時点を記述するためのシステムです。エポックタイムを理解することは、開発者、システム管理者、およびコンピューティングでタイムスタンプを扱うすべての人にとっての基本です。

エポックタイムとは

定義

エポック タイムは、「エポック」と呼ばれる固定基準点からの時間単位 (通常は秒) の連続カウントとして時間を表します。

Epoch Timestamp = Current Time - Epoch Start Time

Example (Unix Epoch):
  Epoch Start: January 1, 1970, 00:00:00 UTC
  Current Time: January 8, 2024, 00:00:00 UTC
  Timestamp: 1704672000 seconds since epoch

Unix エポック (POSIX 時間)

最も広く使用されているエポック システムは Unix エポック (POSIX 時間) です。

Unix Epoch Reference:
  Start Date: January 1, 1970, 00:00:00 UTC
  Time Units: Seconds (some systems use milliseconds)
  Notation: 32-bit signed integer (common) or 64-bit
  Max Range (32-bit): 1901-12-13 to 2038-01-19
  Current Use: Linux, Unix, macOS, most programming languages

興味深い事実: Unix エポックが選択されたのは、Unix が開発された時点での概数であり、計算が簡単になり、ほとんどの実用的な用途で負のタイムスタンプが回避されるためです。

Unix エポックの歴史

Unix エポックは 1970 年代初頭に確立されました。

  • 1970: Unix エポック日付が選択されました (1970 年 1 月 1 日)
  • 1971-1973: 初期の Unix システムでは time_t 型 (32 ビット) が使用されていました。
  • 1988: POSIX 標準が正式に Unix 時間を採用
  • 2000年代: 2038年問題を回避するために、ほとんどのシステムが64ビットtime_tに移行しました。
  • 2020年代: 最新のシステムは64ビットのエポックタイムスタンプを使用しています

なぜ 1970 年なのか? それは Unix が開発され始めた頃であり、ほとんどのコンピュータ システムが存在する前の便利な「ゼロ ポイント」を表しており、初期のコンピューティングの歴史における負のタイムスタンプを回避していました。

異なるエポック システム

共通のエポック参照

1. Unix Epoch (POSIX)
   Start: January 1, 1970, 00:00:00 UTC
   Units: Seconds (or milliseconds)
   Usage: Unix, Linux, macOS, most programming languages

2. Windows FILETIME
   Start: January 1, 1601, 00:00:00 UTC
   Units: 100-nanosecond intervals
   Usage: Windows file systems, NTFS

3. Mac HFS/HFS+ Epoch
   Start: January 1, 1904, 00:00:00 UTC
   Units: Seconds
   Usage: Classic Mac OS (pre-OS X)

4. GPS Epoch
   Start: January 6, 1980, 00:00:00 UTC
   Units: Seconds
   Usage: GPS systems, navigation

5. NTP Timestamp
   Start: January 1, 1900, 00:00:00 UTC
   Units: Seconds (64-bit)
   Usage: Network Time Protocol

6. WebKit/Chrome Epoch
   Start: January 1, 1601, 00:00:00 UTC
   Units: Microseconds
   Usage: Web browsers (Date object)

重要: タイムスタンプを変換する前に、システムまたは API がどのエポック システムを使用しているかを必ず確認してください。

JavaScript エポック

JavaScript はミリ秒単位で Unix エポックを使用します。

// JavaScript Date uses Unix epoch in milliseconds
const now = Date.now();
console.log(now);  // e.g., 1704672000000 (milliseconds)

// Convert to seconds
const nowSec = Math.floor(Date.now() / 1000);
console.log(nowSec);  // e.g., 1704672000 (seconds)

// Create from Unix epoch seconds
const date = new Date(1704672000 * 1000);
console.log(date.toISOString());  // "2024-01-08T00:00:00.000Z"

Python エポック

Python の time.time() は Unix エポックを秒単位で使用します。

import time
from datetime import datetime

# Get current Unix timestamp (seconds)
now_ts = time.time()
print(now_ts)  # e.g., 1704672000.123

# Create datetime from Unix timestamp
dt = datetime.fromtimestamp(1704672000)
print(dt)  # 2024-01-08 00:00:00

# Get UTC timestamp
now_utc = datetime.now(timezone.utc).timestamp()
print(now_utc)  # e.g., 1704672000

Java エポック

Java は、Unix エポックをミリ秒単位で使用します (JavaScript と一致します)。

import java.time.Instant;

// Get current timestamp (milliseconds)
long nowMs = System.currentTimeMillis();
System.out.println(nowMs);  // e.g., 1704672000000

// Get from Instant (Java 8+)
Instant now = Instant.now();
long ts = now.getEpochSecond();
System.out.println(ts);  // e.g., 1704672000

// Create Instant from Unix timestamp
Instant instant = Instant.ofEpochSecond(1704672000);
System.out.println(instant);  // 2024-01-08T00:00:00Z

タイムスタンプの制限と範囲

32 ビット符号付き整数の制限

従来の Unix タイムスタンプは 32 ビットの符号付き整数を使用します。

32-bit Signed Integer Range:
  Min Value: -2147483648 (seconds)
  Max Value: 2147483647 (seconds)
  Min Date: December 13, 1901, 20:45:52 UTC
  Max Date: January 19, 2038, 03:14:07 UTC
  Current Date: January 8, 2024
  Time to Overflow: ~14 years

重大: 2038 年 1 月 19 日、03:14:07 UTC は「2038 年問題」として知られています。32 ビット Unix タイムスタンプがオーバーフローして負の値にラップし、多くのシステムが破壊されます。

64 ビットのタイムスタンプ

最新のシステムでは、64 ビットのタイムスタンプを使用してオーバーフローの問題を解決しています。

64-bit Signed Integer Range:
  Min Value: -9223372036854775808 (seconds)
  Max Value: 9223372036854775807 (seconds)
  Min Date: ~293 billion years BCE
  Max Date: ~293 billion years CE
  Practical Limit: Effectively infinite for all practical purposes
  Current Date: January 8, 2024

ベスト プラクティス: 2038 年問題やその他のオーバーフローの問題を回避するために、新しいシステムでは常に 64 ビットのタイムスタンプを使用してください。

ミリ秒と秒精度

システムが異なれば、使用される精度も異なります。

Second Precision (Traditional Unix):
  Units: Seconds since epoch
  Range (32-bit): 136 years
  Use: Unix/Linux systems, APIs, databases
  Example: 1704672000

Millisecond Precision (Modern Systems):
  Units: Milliseconds since epoch
  Range (32-bit): ~49 days (not practical)
  Range (64-bit): ~293 million years
  Use: JavaScript, Java, most modern APIs
  Example: 1704672000000

変換式:

> Seconds to Milliseconds: seconds * 1000
> Milliseconds to Seconds: milliseconds / 1000
>

2038 年問題

2038 年問題とは何ですか?

2038 年問題は、32 ビット署名された Unix タイムスタンプが 2038 年 1 月 19 日の 03:14:07 UTC にオーバーフローするという時間計算のバグです。

Overflow Timestamp: 2147483647
Date: January 19, 2038, 03:14:07 UTC

After Overflow (Signed 32-bit wraps to negative):
Next Second: -2147483648
Date: December 13, 1901, 20:45:52 UTC

重大な影響: 32 ビット タイムスタンプを使用するシステムでは、2038 年 1 月 19 日以降に障害が発生するか、不正確な日付が生成されます。

影響を受けるシステム

2038 年問題の影響を受ける可能性のあるシステム:

  • レガシー Unix システムでは依然として 32 ビット time_t が使用されています
  • メモリが限られている組み込みシステム
  • 古いデータベース システム
  • 32 ビットのタイムスタンプを使用するファイル システム
  • 32 ビット時間フィールドを持つネットワーク プロトコル
  • 一部の API はまだ 32 ビット整数を使用しています

ソリューション

Solution 1: Upgrade to 64-bit
  - Use time64_t or equivalent
  - Increases range to ~293 billion years
  - Required for long-term systems

Solution 2: Offset Timestamps
  - Store timestamps with epoch offset
  - Example: Store "years since 2000" instead of seconds since 1970
  - Requires conversion on read/write

Solution 3: Use Alternative Formats
  - Use ISO 8601 strings (no overflow)
  - Use datetime types with larger range
  - Store year, month, day separately

予防策: 新しいシステムを設計するときは、常に、より広い範囲の 64 ビットのタイムスタンプまたは日時オブジェクトを使用してください。

エポック間の変換

Unix から Windows へのファイルタイム

function unixToWindowsFiletime(unixTimestamp) {
  // Unix to FILETIME: 100-nanosecond intervals since 1601-01-01
  const WINDOWS_EPOCH = 0x019DB1DED53E8000; // FILETIME of Unix epoch
  const NANOSECONDS_PER_MILLISECOND = 10000;

  const filetime = (unixTimestamp * 1000 + 11644473600000) * NANOSECONDS_PER_MILLISECOND;

  // For large numbers, use BigInt
  return BigInt(unixTimestamp) * 10000n + 116444736000000000n;
}

// Example
const filetime = unixToWindowsFiletime(1704672000);
console.log(filetime);  // 1336477752000000000

Windows FILETIME から Unix へ

function windowsFiletimeToUnix(filetime) {
  const NANOSECONDS_PER_MILLISECOND = 10000;

  // FILETIME to Unix: subtract Windows epoch
  const unixMs = (filetime - 116444736000000000) / 10000n;

  return Number(unixMs / 1000n);
}

// Example
const filetime = 133647752000000000n;
const unixTs = windowsFiletimeToUnix(filetime);
console.log(unixTs);  // 1704672000

Unix から GPS 時間

import datetime

def unix_to_gps(unix_timestamp):
    """Convert Unix timestamp to GPS timestamp"""
    # GPS epoch: January 6, 1980
    # Unix epoch: January 1, 1970
    # Difference: 315964800 seconds
    GPS_EPOCH_OFFSET = 315964800

    return unix_timestamp - GPS_EPOCH_OFFSET

def gps_to_unix(gps_timestamp):
    """Convert GPS timestamp to Unix timestamp"""
    GPS_EPOCH_OFFSET = 315964800
    return gps_timestamp + GPS_EPOCH_OFFSET

# Example
unix_ts = 1704672000
gps_ts = unix_to_gps(unix_ts)
print(f"GPS Timestamp: {gps_ts}")  # 5355687200

Unix から Mac への HFS 時間

import datetime

def unix_to_mac_hfs(unix_timestamp):
    """Convert Unix timestamp to Mac HFS timestamp"""
    # Mac HFS epoch: January 1, 1904
    # Unix epoch: January 1, 1970
    # Difference: -2082844800 seconds (Mac is earlier)
    MAC_EPOCH_OFFSET = -2082844800

    return unix_timestamp - MAC_EPOCH_OFFSET

def mac_hfs_to_unix(mac_timestamp):
    """Convert Mac HFS timestamp to Unix timestamp"""
    MAC_EPOCH_OFFSET = -2082844800
    return mac_timestamp + MAC_EPOCH_OFFSET

# Example
unix_ts = 1704672000
mac_ts = unix_to_mac_hfs(unix_ts)
print(f"Mac HFS Timestamp: {mac_ts}")  # 3787516800

実際の応用例

期間の計算

import time

def calculate_duration(start_ts, end_ts):
    """Calculate duration between two Unix timestamps"""
    duration_seconds = end_ts - start_ts

    hours = duration_seconds // 3600
    minutes = (duration_seconds % 3600) // 60
    seconds = duration_seconds % 60

    return f"{hours}h {minutes}m {seconds}s"

# Example
start = 1704587200  # 2024-01-07 00:00:00
end = 1704673600    # 2024-01-08 00:00:00
print(calculate_duration(start, end))  # "24h 0m 0s"

未来/過去の時間の計算

function timeUntil(targetTimestamp) {
  const now = Date.now() / 1000;
  const diff = targetTimestamp - now;

  if (diff <= 0) {
    return { type: 'past', text: 'Already passed' };
  }

  const days = Math.floor(diff / 86400);
  const hours = Math.floor((diff % 86400) / 3600);
  const minutes = Math.floor((diff % 3600) / 60);

  return {
    type: 'future',
    text: `${days} days, ${hours} hours, ${minutes} minutes`
  };
}

// Calculate time until end of 2037
const target = 2155999999; // December 31, 2037
console.log(timeUntil(target));
// "511 days, 2 hours, 33 minutes"

日付範囲の検証

import time

def is_valid_unix_timestamp(ts, allow_future=True):
    """Validate Unix timestamp is within reasonable range"""
    # Minimum: January 1, 1970
    MIN_TIMESTAMP = 0

    # Maximum: January 19, 2038 (32-bit limit)
    MAX_TIMESTAMP = 2147483647

    if ts < MIN_TIMESTAMP:
        return False, "Timestamp is before Unix epoch"

    if not allow_future and ts > time.time():
        return False, "Timestamp is in the future"

    if ts > MAX_TIMESTAMP:
        return False, "Timestamp exceeds 32-bit limit"

    return True, "Valid"

# Example
print(is_valid_unix_timestamp(1704672000))  # (True, "Valid")
print(is_valid_unix_timestamp(-1000))  # (False, "Timestamp is before Unix epoch")
print(is_valid_unix_timestamp(3000000000))  # (False, "Timestamp exceeds 32-bit limit")

バッチ変換

function convertUnixTimestamps(timestamps) {
  return timestamps.map(ts => {
    const date = new Date(ts * 1000);
    return {
      timestamp: ts,
      isoString: date.toISOString(),
      utcString: date.toUTCString(),
      localString: date.toLocaleString()
    };
  });
}

// Example batch conversion
const timestamps = [1704587200, 1704673600, 1704760000];
const results = convertUnixTimestamps(timestamps);
console.log(results);
/*
[
  {
    timestamp: 1704587200,
    isoString: "2024-01-07T00:00:00.000Z",
    utcString: "Sun, 07 Jan 2024 00:00:00 GMT",
    localString: "1/7/2024, 12:00:00 AM"
  },
  ...
]
*/

ベストプラクティス

タイムスタンプ選択ガイドライン

When choosing timestamp precision:
  ✅ Use seconds for Unix/Linux compatibility
  ✅ Use milliseconds for JavaScript/Java/Web compatibility
  ✅ Use 64-bit integers for future-proof systems
  ✅ Use ISO 8601 strings for cross-system compatibility
  ✅ Document epoch system in API specifications
  ❌ Don't mix precision levels in same API
  ❌ Don't use 32-bit timestamps for long-term systems
  ❌ Don't assume all systems use Unix epoch

ストレージに関する推奨事項

Database storage:
  ✅ Store as TIMESTAMP or DATETIME (64-bit)
  ✅ Store timezone information separately
  ✅ Use UTC for all storage
  ✅ Validate timestamp ranges on input
  ❌ Don't store as VARCHAR or STRING
  ❌ Don't store local times without timezone metadata
  ❌ Don't use 32-bit integers for new systems

API 設計

REST API design:
  ✅ Use ISO 8601 in JSON responses (e.g., "2024-01-08T00:00:00Z")
  ✅ Include timezone information (Z or offset)
  ✅ Document timestamp precision (seconds or milliseconds)
  ✅ Support both input formats for flexibility
  ✅ Return descriptive errors for invalid timestamps
  ❌ Don't use locale-specific formats in APIs
  ❌ Don't assume client timezone
  ❌ Don't silently correct invalid timestamps

テスト戦略

import datetime

def test_epoch_conversions():
    """Test epoch conversion edge cases"""
    test_cases = [
        ("Unix epoch start", 0, datetime.datetime(1970, 1, 1)),
        ("Current time", 1704672000, datetime.datetime(2024, 1, 8)),
        ("Year 2038 limit", 2147483647, datetime.datetime(2038, 1, 19, 3, 14, 7)),
        ("Negative timestamp", -86400, datetime.datetime(1969, 12, 31, 0, 0, 0)),
    ]

    for name, timestamp, expected in test_cases:
        result = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
        assert result == expected, f"Failed: {name}"

    print("All epoch conversion tests passed!")

test_epoch_conversions()

関連ツール

追加リソース

ほとんどのアプリケーションでは、Unix エポック (1970 年 1 月 1 日) が事実上の標準です。ただし、システムによって異なる基準日が使用される可能性があるため、外部システム、API、またはレガシー データと統合する場合は、常にエポック システムを確認してください。

クイックリファレンス

Common Epoch Timestamps:
  0: January 1, 1970, 00:00:00 UTC (Unix epoch start)
  946684800: January 1, 2000, 00:00:00 UTC
  1577836800: January 1, 2020, 00:00:00 UTC
  1704067200: January 1, 2024, 00:00:00 UTC
  2147483647: January 19, 2038, 03:14:07 UTC (32-bit max)
  253402300799: December 31, 9999, 23:59:59 UTC (Common limit)