[C#] Unix Timestamp
Unix Timestamp란?
유닉스 타임스탬프(Unix Timestamp)란, 1970년 1월 1일 00:00:00 (UTC) 부터의 경과 시간을 초로 환산하여 정수로 나타낸 값이다. 이 값은 윤초를 무시하며, POSIX 시간이나 Epoch 시간이라고 부르기도 한다.
32비트 정수형을 쓰고 있었으므로 2038년 1월 19일 3시 14분 07초가 지나는 순간 오버플로로 인해서 더 이상 값을 정상적으로 나타낼 수 없는 문제가 존재한다. 이 문제를 Y2K38 문제라고 한다.
unsigned 형으로 전환하면 2106년까지 늦출 수 있지만 음수형을 표현할 수 없으므로 1970년 이전의 시간을 나타낼 수 없는 문제가 존재하고, 64비트 int형으로 바꾸게 되면 2922,7702,6596년까지 표현할 수 있어 사실상 앞으로 문제가 생길 가능성이 없어지지만 기존의 프로그램들이 바이너리 수준의 호환성 문제로 정상 작동이 어려울 수 있다는 것이 문제다.
현재 컴퓨터들이 64비트 아키텍처로 넘어가는 단계이기 때문에 시간이 흐르면 자연스럽게 해결될 것이라고 한다.
많이 사용하는 RDB인 MySQL에서 해당 문제의 버그가 있었으나, 8.0.28버전 기준으로 해당 문제가 개선되었다고 한다. Linux, MacOS, Windows 64-bit 플랫폼에서는 해당 버전부터 timestamp의 날짜 지원 범위는 1970-01-01 00:00:00.000000 ~ 3001-01-18 23:59:59.000000으로 확장되었으며, 이후 날짜 사용이 필요한 경우 datetime 사용을 가이드하고 있다.
C#에서의 사용
// Utc기준 현재 시각
DateTime dateTimeNow = DateTime.UtcNow;
// 1970년 1월 1일 00:00:00 (UTC)
DateTime dateTimeEpoch = DateTime.UnixEpoch;
// Utc기준 현재 시각
DateTimeOffset offsetNow = DateTimeOffset.UtcNow;
// 1970년 1월 1일 00:00:00 (UTC)
DateTimeOffset offsetEpoch = DateTimeOffset.UnixEpoch;
DateTime, 혹은 DateTimeOffset 둘 중 하나의 구조체를 선택하여 사용할 수 있다.
DateTime과 DateTimeOffset의 차이는 추후 다른 글에서 자세히 다뤄보도록 하고, 여기서는 DateTime은 표준 시간대 사용과 관계 없이 시간값을 다루고, DateTImeOffset은 시간대값에 따라 다른 시간값을 가진다는 점만 설명하도록 하겠다. 서로 다른 시간대의 값을 사용하는 것이 아니라면 둘의 결과값은 동일하다.
위의 값은 다음의 출력에 해당한다.
// DateTime 사용 시
double dateTimeUnixSecond = DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds;
double dateTimeUnixMillisecond = DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalMilliseconds;
// DateTimeOffset 사용 시
double unixSecond = DateTimeOffset.UtcNow.Subtract(DateTimeOffset.UnixEpoch).TotalSeconds;
double unixMilisecond = DateTimeOffset.UtcNow.Subtract(DateTimeOffset.UnixEpoch).TotalMilliseconds;
unix time값을 얻는 방법은 각각 위와 같다. unix time값을 얻고 싶은 값에서 unix 기준 시각(1970년 1월 1일 00:00:00 (UTC))을 빼고 second, 혹은 millisecond 값을 얻으면 된다.
DateTime과 DateTimeOffset의 TotalSeconds/TotalMilliseconds 값을 얻으면 double형으로 출력되는데, 이는 0.0000001초까지 표기된 시간값이다.
TotalSecond와 TotalMilliseconds 두 값을 출력하면 다음과 같다.
TotalSecond는 초 단위 값까지, TotalMillisecond는 0.001초 단위 값 까지의 정수형 값을 가진다.
필요에 따라 둘 중 필요한 값을 선택하여 사용하면 되며, mysql에 저장하려면 Column Type을 TIMESTAMP(3)으로 하면 MilliSecond까지 저장이 가능하다. TIMESTAMP(6)를 하면 0.000001의 micro 초 단위 값까지 저장할 수 있으며, 저장할 값의 정수 파트를 저장하면 된다.
저장한 unix timestamp 값을 다시 DateTime 혹은 DateTimeOffset형으로 변환하여 사용하려면 다음과 같이 사용하면 된다.
(저장된 값은 정수값만을 저장한 기준이다.)
DateTime dateTimeByUnixSecond = DateTime.UnixEpoch.AddSeconds(dateTimeUnixSecond);
DateTime dateTimeByUnixMilliSecond = DateTime.UnixEpoch.AddMilliseconds(dateTimeUnixMillisecond);
DateTimeOffset offsetByUnixSecond = DateTimeOffset.UnixEpoch.AddSeconds(offsetUnixSecond);
DateTimeOffset offsetByUnixMilliSecond = DateTimeOffset.UnixEpoch.AddMilliseconds(offsetUnixMilisecond);