C# 날짜 계산의 모든 것

포멧은 ISO 8601 기본 규칙 을 따른다

ISO 8601은 국제 표준(YYYY-MM-DDThh:mm:ss±hh:mm)으로, 시간대(오프셋), 밀리초, **UTC 여부(Z)**까지 표현할 수 있습니다.

1. ISO 8601 기본 규칙

구성 요소예시설명
연도(YYYY)20254자리 연도
월(MM)0901~12
일(DD)0401~31
구분자T날짜와 시간 사이에 T 필수
시(HH)2100~23
분(mm)3000~59
초(ss)4500~59
밀리초(.fff).123선택적, 최대 7자리(틱까지)
시간대Z, +09:00Z는 UTC, +09:00은 한국

날짜 + 시간 (로컬 시간, 오프셋 없음)

형식예시설명
YYYY-MM-DDTHH:mm2025-09-04T21:30ISO 기본형
YYYY-MM-DDTHH:mm:ss2025-09-04T21:30:15초까지 포함
YYYY-MM-DDTHH:mm:ss.fff2025-09-04T21:30:15.123밀리초 포함
YYYY-MM-DDTHH:mm:ss.fffffff2025-09-04T21:30:15.1234567틱(100ns)까지

UTC 시간(Zulu 시간)

형식예시설명
YYYY-MM-DDTHH:mmZ2025-09-04T12:30ZZ → UTC
YYYY-MM-DDTHH:mm:ssZ2025-09-04T12:30:15Z초 포함
YYYY-MM-DDTHH:mm:ss.fffZ2025-09-04T12:30:15.123Z밀리초 포함

오프셋(시간대) 포함

형식예시설명
±hh:mm+09:00한국
±hh:mm-07:00LA(서머타임)
±hhmm+0900구버전 ISO 8601
±hh+09드물게 사용
예시의미
2025-09-04T21:30+09:00한국시간 21:30
2025-09-04T14:30+02:00파리시간 14:30
2025-09-04T05:30-07:00LA시간 05:30

밀리초 + 오프셋

형식예시설명
YYYY-MM-DDTHH:mm:ss.fff±hh:mm2025-09-04T21:30:15.123+09:00한국, 밀리초 포함
YYYY-MM-DDTHH:mm:ss.fffZ2025-09-04T12:30:15.123ZUTC, 밀리초 포함

CultureInfo.InvariantCulture

문화권(로캘)에 영향을 받지 않는, 변하지 않는 중립 문화권.
날짜/숫자 “기계가 읽는 포맷”을 파싱/서식화할 때(로그, 파일, 프로토콜, DB 키 등). 사용자의 PC가 한국/미국 등 어떤 문화권이어도 동일하게 동작합니다.

DateTimeStyles.RoundtripKind

문자열 → DateTime 파싱 시 Kind(Utc/Local/Unspecified)를 최대한 “원본 그대로” 보존하도록 지시하는 옵션.
ToString("o")(ISO 8601 Round-trip)로 직렬화한 뒤 다시 Parse로 복원할 때, 원본의 Kind를 유지하고 싶을 때.

Tip: 실제 시간대/오프셋을 다뤄야 할 때는 DateTimeOffset + TimeZoneInfo 사용이 정석입니다. DateTime은 Kind만 있고 구체 오프셋을 담지 못합니다.

TimeSpan.FromHours

시간”을 나타내는 TimeSpan을 시간 단위(소수 포함)로 생성.
오프셋 지정, 시간 더하기/빼기, 타임아웃 등.

DateTimeOffset.ToOffset(TimeSpan)

같은 “순간(UTC 시각)”을 유지한 채, 표현 오프셋만 바꿔 새 DateTimeOffset을 반환. (로컬 시계시각은 자동으로 재계산됨)
동일한 UTC 순간을 다른 시간대/오프셋 기준의 “현지시각”으로 보여줄 때.

중요: ToOffset은 “고정된 오프셋”을 적용할 뿐 “어느 시간대인지” 계산해 주지 않습니다. 서머타임(DST) 같은 규칙 반영은 **TimeZoneInfo**로 먼저 해당 시점의 올바른 오프셋을 구한 뒤 그 오프셋을 ToOffset에 넣어야 합니다.

DateTimeOffset.Offset (속성)

해당 DateTimeOffset이 갖는 오프셋(TimeSpan) 값을 돌려줍니다.
현재 값이 어느 오프셋인지 확인하거나, 다른 값에 재사용할 때.

실전 팁 요약

  • 기계 파싱/출력: CultureInfo.InvariantCulture + 명시적 포맷("o"/"yyyy-MM-ddTHH:mm:ss")
  • DateTime 직렬화 왕복: "o" + DateTimeStyles.RoundtripKind
  • 오프셋 계산/적용: TimeSpan.FromHours(...)
  • 다른 시간대 표시: TimeZoneInfo.GetUtcOffset(특정시각)DateTimeOffset.ToOffset(그 오프셋)
  • 현재 오프셋 확인: dateTimeOffset.Offset