Guide

신기원 시간 설명

소개

Epoch 시간(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

유닉스 에포크(POSIX 시간)

가장 널리 사용되는 epoch 시스템은 Unix epoch(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 epoch가 선택된 이유는 Unix가 개발될 당시 어림수였기 때문에 계산이 간단하고 대부분의 실제 사용에서 음수 타임스탬프가 방지되었기 때문입니다.

유닉스 시대의 역사

Unix 시대는 1970년대 초에 확립되었습니다.

  • 1970: 선택한 Unix 시대 날짜(1970년 1월 1일)
  • 1971-1973: 초기 Unix 시스템에서는 time_t 유형(32비트)을 사용했습니다.
  • 1988: 공식적으로 Unix 시간을 채택한 POSIX 표준
  • 2000년대: 2038년 문제를 피하기 위해 대부분의 시스템이 64비트 time_t로 전환되었습니다.
  • 2020년대: 최신 시스템은 64비트 에포크 타임스탬프를 사용합니다.

왜 1970년입니까? 이는 대략 Unix가 개발된 시기였으며 대부분의 컴퓨터 시스템이 존재하기 전 편리한 "0점"을 나타내어 초기 컴퓨팅 역사에 대한 음수 타임스탬프를 피했습니다.

다양한 에포크 시스템

공통 에포크 참조

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는 밀리초 단위로 Unix epoch를 사용합니다.

// 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의 time.time()은 Unix epoch(초)를 사용합니다.

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는 밀리초 단위로 Unix epoch를 사용합니다(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-01-19 이후 오류가 발생하거나 잘못된 날짜를 생성합니다.

영향을 받는 시스템

2038년 문제의 영향을 받을 가능성이 있는 시스템:

  • 여전히 32비트 time_t를 사용하는 레거시 Unix 시스템
  • 메모리가 제한된 임베디드 시스템
  • 오래된 데이터베이스 시스템
  • 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비트 타임스탬프나 날짜/시간 개체를 사용하세요.

시대 간 변환

유닉스에서 윈도우로 FILETIME

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

유닉스에서 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)