CodeGym /행동 /C# SELF /시간 작업의 기본 타입들

시간 작업의 기본 타입들

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

1. DateTime 타입 알아보기

날짜랑 시간은 모든 비즈니스 로직의 기본 벽돌 같은 거라서, 아무리 간단한 프로젝트라도 무시할 수 없어. 언제 사용자가 가입했는지, 언제 메일을 보내야 하는지, 비행 스케줄 처리, 타임존... 다 날짜랑 관련 있지! 근데 실제로 날짜랑 시간 다루는 게 프로그래밍에서 제일 골치 아픈 주제 중 하나야. 😅

C#에서는 시간 다룰 때 특히 중요한 타입이 두 개 있어: DateTime이랑 DateTimeOffset. 간단히 말하면, 하나는 단순한 상황용이고, 다른 하나는 타임존이나 정확한 시간 저장이 필요할 때 써.

DateTime이 뭐야?

DateTime 타입은 System 네임스페이스에 정의된 구조체야. 날짜와 시간을 100 나노초(1/10십억초) 단위로 저장할 수 있어.

  • 값 타입(struct)이라서 값 복사됨.
  • 날짜랑 시간 둘 다 저장함.
  • 날짜만(2025-05-24) 또는 날짜+시간(2025-05-24 15:17:42) 둘 다 저장 가능.
  • 명시적으로 지정하지 않으면 타임존 정보 없음.

2. DateTime 만들기

여러 방법이 있는데, 주요한 것만 볼게.

1. 현재 날짜와 시간

DateTime now = DateTime.Now;           // 컴퓨터의 로컬 시간
DateTime utcNow = DateTime.UtcNow;     // 그리니치 표준시(UTC)
  • Now — "네 컴퓨터 기준"이고, Windows의 로컬 타임존을 반영해.
  • UtcNow — "유니버설", 즉 전세계 공통 시간. DB나 글로벌 시스템에서 시간 저장할 때 진짜 편함.

2. 생성자

// 연, 월, 일
var date1 = new DateTime(2025, 5, 24);

// 연, 월, 일, 시, 분, 초
var date2 = new DateTime(2025, 5, 24, 12, 0, 0);

// 연, 월, 일, 시, 분, 초, 밀리초
var date3 = new DateTime(2025, 5, 24, 12, 0, 0, 500);

월은 0부터 시작 안 해! 즉, 1월은 1, 12월은 12야.

3. 문자열에서 파싱

날짜가 문자열로 들어오는 경우가 진짜 많아! 예를 들어, 사용자가 직접 날짜를 입력할 때.

string userInput = "2025-05-24 18:30";
DateTime parsed = DateTime.Parse(userInput); // 예외 발생할 수 있음!

안전하게 파싱하려면 TryParse를 써:

string input = "2025-05-24 18:30";
if (DateTime.TryParse(input, out DateTime result))
{
    Console.WriteLine($"변환 성공: {result}");
}
else
{
    Console.WriteLine("문자열을 날짜로 변환 실패.");
}

4. "시간 없는" 날짜 얻기

DateTime today = DateTime.Today; // 오늘 날짜, 시간은 00:00:00

날짜와 시간 컴포넌트 추출

모든 속성은 바로 꺼낼 수 있어:

var dt = new DateTime(2025, 5, 24, 15, 17, 42);

int year = dt.Year;         // 2025
int month = dt.Month;       // 5 (5월)
int day = dt.Day;           // 24
int hour = dt.Hour;         // 15
int minute = dt.Minute;     // 17
int second = dt.Second;     // 42
DayOfWeek dow = dt.DayOfWeek; // 금요일

3. DateTime 타입 다루기

날짜 더하기/빼기

프로그래밍에서 시간은 순식간에 지나가니까, "마감까지 몇 시간 남았지?" 이런 거 직접 계산하지 말고, 클래스 메서드 써:

DateTime now = DateTime.Now;
DateTime tomorrow = now.AddDays(1); // 내일
DateTime afterFiveHours = now.AddHours(5); // 5시간 후
DateTime inTenMinutes = now.AddMinutes(10); // 10분 후

두 날짜의 차이: TimeSpan

두 날짜의 차이는 별도의 타입 TimeSpan으로 나타내:

DateTime deadline = new DateTime(2026, 6, 1);
DateTime now = DateTime.Now;

TimeSpan untilDeadline = deadline - now;

Console.WriteLine($"마감까지 남은 일수: {untilDeadline.Days}");
Console.WriteLine($"마감까지 남은 시간: {untilDeadline.TotalHours:N2}");

TimeSpan은 "차이"지, "특정 날짜/시간"이 아니야!

미래/과거 날짜 체크

if (deadline > now)
    Console.WriteLine("마감 아직 남았어!");
else
    Console.WriteLine("마감 지났어! 빨리 제출하자!");

4. 날짜가 내부적으로 저장되는 방식

날짜 더하고 빼기 쉽게 하려고, 프로그래머들은 모든 날짜를 우리 시대 시작부터 지난 초의 수로 저장하기로 했어. 범위 값은:

속성
최소 날짜
DateTime.MinValue
= 0001-01-01 00:00:00
최대 날짜
DateTime.MaxValue
= 9999-12-31 23:59:59.9999999
단위 1 틱 = 100 나노초

DateTime은 그냥 초가 아니라, "틱"(ticks)의 개수를 저장해. 기준 날짜는 0001년 1월 1일(공룡은 모름, 프로그래머 달력은 엄격함). 한 틱 = 100 나노초야.

5. DateTimeOffset 타입

가끔 DateTime만으로 부족할 때가 있어. 예를 들어, 회사가 두 나라에 있는데, 타임존이 다르고, 모든 미팅이 "내 시간 기준"으로 잡혀있을 때. 어떻게 해야 할까?

DateTime으로 저장된 시간은 보통 "추상적"이야: 그냥 숫자랑 틱일 뿐, 어느 타임존인지 명확히 안 알려주면 모름. 예를 들어, "2025-05-24 15:00"을 받았을 때, 이게 나이로비 시간인지, 바그다드인지, 베를린인지 알 수 없어(썸머타임까지 있으면 더 헷갈림!).

그래서 정확한 시점이 필요한 경우, 즉 "달력 날짜"가 아니라 "진짜 순간"이 필요할 때 두 번째 타입 DateTimeOffset이 나왔어. DateTimeOffset을 만들 때 오프셋(예: 나이로비 +3시간)을 지정할 수 있어:


var localTime = new DateTimeOffset(2025, 5, 24, 15, 0, 0, TimeSpan.FromHours(3));

DateTimeOffset을 써야 할 때:

  • 정확한 시점이 필요할 때(예: 서버 시간에 맞춘 로그 이벤트).
  • 프로그램이 여러 타임존의 사용자랑 동작할 때.
  • 타임존 정보까지 저장/전달해야 할 때(예: 트랜잭션, 이벤트, 스케줄).

6. DateTimeOffset 만들기

  1. 현재 시점
    DateTimeOffset now = DateTimeOffset.Now; // 로컬 시간 + 오프셋
    DateTimeOffset utc = DateTimeOffset.UtcNow; // UTC(오프셋 0)
    
  2. 명시적으로 만들기
    // 연, 월, 일, 시, 분, 초, 오프셋(예: +2시간)
    DateTimeOffset custom = new DateTimeOffset(2025, 5, 24, 20, 0, 0, TimeSpan.FromHours(2));
    
  3. DateTime에서 변환
    DateTime dt = DateTime.Now;
    DateTimeOffset dto = new DateTimeOffset(dt); // 로컬 오프셋 자동 적용
    

컴포넌트 추출

DateTimeOffset dto = DateTimeOffset.Now;
var datePart = dto.Date;      // 날짜만
var timePart = dto.TimeOfDay; // 시간만
var offset = dto.Offset;      // UTC 기준 오프셋, 예: 03:00:00

타임존 변환

오프셋 마법:

// UTC로 변환
var now = DateTimeOffset.Now;
var utc = now.ToUniversalTime();
Console.WriteLine(utc); // 그리니치 표준시

// 다른 타임존으로 변환
var berlinTime = utc.ToOffset(TimeSpan.FromHours(2));
Console.WriteLine(berlinTime); // 베를린(CET +2)

7. DateTime이랑 DateTimeOffset 언제 써야 해?

선택 철학

뭔가 단순하고 로컬한 거라면 — 예를 들어, 생일, 게시글 날짜, 설문 마감 15:00 이런 거면 보통 DateTime이면 충분해. 이런 경우엔 절대적인 시간이 중요하지 않고, 그냥 그날 그 시간에 일이 일어났다는 게 중요하지, 타임존은 신경 안 써도 돼.

근데 정확한 시점이랑 타임존까지 기록해야 한다면, 예를 들어 로그, 트랜잭션, 분산 시스템 등에서는 DateTimeOffset을 쓰는 게 좋아. 시스템끼리 시간 주고받을 때 헷갈릴 일 없고, 특히 타임존이 다르면 필수야.

시나리오 타입 이유
생일
DateTime
날짜만 중요, 타임존은 보통 신경 안 씀
로그인 시간
DateTimeOffset
정확한 시점과 오프셋이 중요함
상품 유효기간
DateTime
만료 날짜만 중요, 타임존은 신경 안 씀
로그 이벤트 시간
DateTimeOffset
항상 오프셋과 함께 저장하는 게 좋음
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION