1. 소개
만약 네가 타임존이 그냥 "몇 시간 더하고/빼면 되는 거 아냐?"라고 생각한다면, 곧 전 세계 프로그래머들이 왜 이걸로 고생하는지 뼈저리게 느끼게 될 거야. 타임존, 썸머타임/윈터타임 변경, "다른 지역 시간으로 바꾸기" 하다가 나오는 이상한 예외들 — 이런 것들이 버그로 이어지고, 찾기도 어렵고, 유저한테 설명하기는 더더욱 힘들어.
제일 골때리는 건: 세상에는 "유니버설"한 시간 개념이 원래 없었고, 앞으로도 없을 거라는 거야 — 예를 들어, 이웃한 두 나라가 썸머타임을 다르게 적용할 수도 있고, 심지어 연중에 갑자기 정책을 바꿀 수도 있어(진짜임!). 예시: 2011년에 사모아는 하루를 통째로 건너뛰고 날짜변경선 반대편으로 넘어갔어.
그래도 C#이랑 .NET에는 이 난장판을 조금이라도 버틸 수 있게 해주는 강력한 도구들이 있어. 오늘은 우리의 구세주 — TimeZoneInfo 타입과 그 기능들을 알아볼 거야. 이게 너랑 네 앱을 살려줄 거야.
타임존 처리가 필요한 순간들
- 유저나 서버가 전 세계 여러 지역에 있을 때
- DB에 날짜/시간을 UTC로 저장하고, 유저한테는 그 지역 시간으로 보여줘야 할 때
- 스케줄, 알림, 온라인 이벤트 계산할 때 ("웨비나가 베를린 시간 19:00에 시작 — 네 지역에선 몇 시?")
- 기업용/글로벌 시스템 개발할 때 (예: 국제 비즈니스용 회계나 CRM)
TimeZoneInfo 타입 개요
TimeZoneInfo는 .NET에서 타임존 정보를 표현하려고 만든 클래스야: UTC 기준 오프셋, 이름, 썸머타임 지원 여부 등등을 담고 있어.
옛날 TimeZone 클래스는 딱 "로컬"이랑 "UTC"만 알았는데, TimeZoneInfo는 시스템에 등록된 모든 타임존(심지어 직접 만든 것도!)에 완전히 접근할 수 있어.
2. 타임존 정보 얻기
로컬과 UTC 타임존
로컬 타임존 정보 얻는 건 진짜 쉬워:
// 로컬(즉, 지금 네 프로그램이 돌아가는 곳)
TimeZoneInfo local = TimeZoneInfo.Local;
// 항상 UTC
TimeZoneInfo utc = TimeZoneInfo.Utc;
Console.WriteLine(local.DisplayName); // 예: (UTC+01:00) Berlin, Vienna
Console.WriteLine(utc.DisplayName); // (UTC) Coordinated Universal Time
사용 가능한 모든 타임존
유저한테 모든 가능한 타임존 리스트를 보여줘야 할 때가 많아(예: 서비스 회원가입할 때):
foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
{
Console.WriteLine($"{tz.Id} | {tz.DisplayName}");
}
이렇게 출력될 거야:
- Central European Standard Time | (UTC+01:00) Berlin, Vienna
- Pacific Standard Time | (UTC-08:00) Pacific Time (US & Canada)
- 등등
시각화: TimeZoneInfo 주요 속성
| 속성 | 설명 |
|---|---|
|
타임존의 시스템 식별자(검색할 때 씀) |
|
유저용 설명(시간/도시 포함) |
|
"표준" 시간 이름 |
|
썸머타임 적용 시 이름 |
|
UTC 기준 오프셋(예: 베를린은 +01:00) |
|
True면 썸머타임/윈터타임 전환 지원 |
3. 타임존 간 시간 변환
이게 바로 우리가 이걸 배우는 이유지! 네가 해야 할 건:
- 한 타임존에서 다른 타임존으로 시간 변환(예: 서버는 UTC로 저장, 유저에겐 그 지역 시간으로 보여주기)
- 썸머타임/윈터타임 전환도 제대로 처리하기
기본 문법
DateTime utcNow = DateTime.UtcNow;
// 예를 들어, 이 시간을 중앙유럽 타임존으로 변환해보자
TimeZoneInfo europeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
DateTime europeTime = TimeZoneInfo.ConvertTimeFromUtc(utcNow, europeZone);
Console.WriteLine($"UTC now: {utcNow}"); // 2024-06-20 10:30:00
Console.WriteLine($"Europe now: {europeTime}"); // 2024-06-20 11:30:00
중요: 내부 계산/저장에는 항상 UTC를 쓰고, "출력"할 때만 원하는 타임존으로 변환해!
타임존 식별자 찾는 법?
Windows에선 타임존 Id가 독특해(예: "Central European Standard Time"), Linux/Unix에선 보통 IANA/Olson 식별자("Europe/Berlin", "America/New_York")를 써.
네 시스템의 식별자 리스트는 TimeZoneInfo.GetSystemTimeZones()로 확인할 수 있어.
4. 임의의 타임존 간 변환
예를 들어, 런던(GMT/UTC+0) 시간을 도쿄(UTC+9)로 바꾸고 싶다고 해보자:
DateTime londonTime = new DateTime(2024, 6, 20, 12, 0, 0, DateTimeKind.Unspecified);
TimeZoneInfo londonZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
TimeZoneInfo tokyoZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
// 1단계: 로컬 시간이라면 먼저 UTC로 변환
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(londonTime, londonZone);
// 2단계: UTC를 도쿄 시간으로 변환
DateTime tokyoTime = TimeZoneInfo.ConvertTimeFromUtc(utc, tokyoZone);
Console.WriteLine($"London: {londonTime} | UTC: {utc} | Tokyo: {tokyoTime}");
썸머타임/윈터타임 전환 처리
TimeZoneInfo는 해당 타임존이 지원하면 썸머타임/윈터타임 전환도 알아서 처리해줘.
TimeZoneInfo eastern = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dateWinter = new DateTime(2024, 1, 1, 12, 0, 0, DateTimeKind.Unspecified);
DateTime dateSummer = new DateTime(2024, 7, 1, 12, 0, 0, DateTimeKind.Unspecified);
Console.WriteLine( TimeZoneInfo.ConvertTimeToUtc(dateWinter, eastern)); // UTC-5 오프셋
Console.WriteLine( TimeZoneInfo.ConvertTimeToUtc(dateSummer, eastern)); // UTC-4 오프셋 — 썸머타임!
위 예시처럼 미국이 썸머타임을 없애기로 해도(매년 이런 얘기 나옴!), 네 OS의 타임존 DB는 계속 업데이트되고, 네 코드는 계속 잘 동작할 거야.
5. 실전 팁 & 흔한 실수
예외와 함정
- 시계가 바뀌는 순간(예: 썸머타임/윈터타임 전환일 새벽 2:30), 어떤 시간은 "존재하지 않거나" "중복"될 수 있어:
예를 들어, "뒤로" 바뀌는 날엔 2:30이 두 번 생기는데, 둘 다 "다른" 시간이야. - 잊지 마: 타임존 리스트는 OS 업데이트로 바뀔 수 있어! 예시: 어떤 나라는 썸머타임을 없애거나 새로 도입하기도 해.
GO TO FULL VERSION