CodeGym /행동 /C# SELF /타임존 다루기: TimeZoneInfo

타임존 다루기: TimeZoneInfo

C# SELF
레벨 15 , 레슨 2
사용 가능

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 주요 속성

속성 설명
Id
타임존의 시스템 식별자(검색할 때 씀)
DisplayName
유저용 설명(시간/도시 포함)
StandardName
"표준" 시간 이름
DaylightName
썸머타임 적용 시 이름
BaseUtcOffset
UTC 기준 오프셋(예: 베를린은 +01:00)
SupportsDaylightSavingTime
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 업데이트로 바뀔 수 있어! 예시: 어떤 나라는 썸머타임을 없애거나 새로 도입하기도 해.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION