DateTime과 DateTimeOffset


742

현재, 우리는 .NET을 처리하는 표준 방법이 DateTime인식 방법 시간대에 s '을 (를) : 우리가 생성 할 때마다 DateTime우리는 UTC (예를 들어, 사용에 그것을 할 DateTime.UtcNow), 우리는 하나를 표시 할 때마다, 우리는 사용자의 로컬 시간으로 다시 UTC에서 변환 .

그것은 잘 작동하지만 DateTimeOffset, 객체 자체에서 현지 시간과 UTC 시간을 캡처하는 방법 에 대해 읽었 습니다. 문제는 DateTimeOffset우리가 이미 해왔 던 것과 비교 하여 사용 하면 어떤 이점이 있습니까?


3
아래에 좋은 답변이 있습니다. 그러나 여전히 DateTimeOffset을 사용하기 시작한 것이 무엇인지 궁금해하고 있습니다.
HappyNomad


스토리지와 관련하여 stackoverflow.com/questions/4715620/… 도 흥미 롭습니다.
Dejan

답변:


1169

DateTimeOffset순간 시간 ( 절대 시간 이라고도 함)을 나타냅니다 . 즉, 나는 모든 사람에게 보편적 인 순간을 의미합니다 ( 윤초 또는 시간 팽창 의 상대 론적 영향을 설명하지 않음 ). 순간적인 시간을 나타내는 또 다른 방법은 DateTimewhere .Kind입니다 DateTimeKind.Utc.

이것은 다른 사람의 달력에있는 위치 인 달력 시간 ( 민간 시간 이라고도 함 )과 다르며 전 세계에 많은 다른 달력이 있습니다. 우리는이 달력 시간대를 호출 합니다 . 일정 시간은로 표현되는 DateTime.Kind이다 DateTimeKind.Unspecified, 또는 DateTimeKind.Local. 그리고 .Local당신이 결과를 사용하는 컴퓨터가 위치한 곳의 묵시적 이해 시나리오에서만 의미가 있습니다. (예를 들어, 사용자의 워크 스테이션)

그렇다면 왜 DateTimeOffsetUTC 대신에 DateTime? 그것은 관점에 관한 것입니다. 비유를 사용합시다 – 우리는 사진 작가 인 것처럼 가장 할 것입니다.

캘린더 타임 라인에 서 있고, 당신 앞에 배치 된 순간 타임 라인에있는 사람을 카메라로 향하고 있다고 상상해보십시오. 일광 절약 시간제 또는 표준 시간대의 법적 정의에 대한 기타 변경으로 인해 시간대 규칙에 따라 카메라를 정렬합니다. (손이 안정적이지 않아 카메라가 흔들립니다.)

사진에 서있는 사람은 카메라의 각도를 볼 수 있습니다. 다른 사람들이 사진을 찍는 경우 다른 각도에서 촬영할 수 있습니다. 이것이 Offset부분의 DateTimeOffset대표입니다.

따라서 카메라에 "동부 표준시"라고 레이블을 지정하면 때로는 -5를 가리키고 때로는 -4를 가리 킵니다. 전 세계에 카메라가 있으며, 모두 다른 라벨이 붙어 있으며, 다른 각도에서 동일한 순간 타임 라인을 가리키는 카메라가 있습니다. 그들 중 일부는 서로 바로 옆에 (또는 위에) 있기 때문에 오프셋을 아는 것만으로는 시간과 관련된 시간대를 결정하기에 충분하지 않습니다.

그리고 UTC는 어떻습니까? 글쎄, 그것은 손이 안정적으로 보장되는 카메라 중 하나입니다. 삼각대에 있고 땅에 단단히 고정되어 있습니다. 아무데도 안가 우리는 그것의 원근 각도를 제로 오프셋이라고 부릅니다.

순간 시간 대 달력 시간 시각화

그렇다면이 비유는 무엇을 말해줍니까? 직관적 인 지침을 제공합니다.

  • 특정 장소를 기준으로 시간을 나타내는 경우 달력 시간으로 a를 사용하여 나타내십시오 DateTime. 한 캘린더를 다른 캘린더와 혼동하지 마십시오. Unspecified당신의 가정이되어야합니다. Local에서 오는 경우에만 유용합니다 DateTime.Now. 예를 들어 DateTime.Now데이터베이스에 가져 와서 저장할 수는 있지만 검색 할 때는 데이터베이스가이라고 가정해야합니다 Unspecified. 로컬 캘린더가 원래 가져온 캘린더와 동일한 캘린더에 의존 할 수 없습니다.

  • 항상 확실해야하는 경우, 즉시 시간을 나타내는 지 확인하십시오. DateTimeOffset이를 적용하거나 DateTime규칙에 따라 UTC 를 사용하십시오 .

  • 순간의 순간을 추적해야하지만 "사용자가 현지 캘린더의 시간을 생각한 시간"을 알고 싶을 경우 - 당신은 해야한다 를 사용합니다 DateTimeOffset. 이것은 기술 및 법적 문제와 같은 시간 관리 시스템에 매우 중요합니다.

  • 이전에 기록한 레코드를 수정해야하는 경우 DateTimeOffset새 오프셋이 여전히 사용자와 관련이있을만큼 오프셋에 충분한 정보가 없습니다. 시간대 식별자 저장 해야합니다 (생각-위치가 변경된 경우에도 새 사진을 찍을 수 있도록 카메라 이름이 필요함).

    또한 .Net 기본 클래스 라이브러리에는 유사한 것이없는 반면, Noda Time 은 이에 대한 표현을 가지고 있음을 지적해야합니다 ZonedDateTime. a DateTimeOffsetTimeZoneInfo.Id값을 모두 저장해야 합니다.

  • 때때로, 당신은 "누구든지 그것을보고있는"현지인 달력 시간을 나타내기를 원할 것입니다. 예를 들어 오늘의 의미를 정의 할 때 오늘은 항상 자정부터 자정이지만, 이는 순간 타임 라인에서 거의 무한한 수의 겹치는 범위를 나타냅니다. (실제로 시간대는 한정되어 있지만 틱까지 오프셋을 표시 할 수 있습니다.) 이러한 상황에서 "누가 묻는 사람"을 제한하는지 이해해야합니다. 단일 시간대로 질문하거나 적절한 순간으로 다시 변환하는 것을 처리합니다.

다음은 DateTimeOffset이 비유를 뒷받침 하는 몇 가지 다른 내용 과 똑바로 유지하기위한 몇 가지 팁입니다.

  • DateTimeOffset값 을 비교하면 비교 하기 전에 먼저 0 오프셋으로 정규화됩니다. 즉, 2012-01-01T00:00:00+00:002012-01-01T02:00:00+02:00같은 순간 순간 참조 그러므로 동등하다.

  • 당신이 어떤 단위 테스트와 필요를 수행하는 경우, 오프셋 (offset) 테스트를 확신 할 수 있습니다 모두DateTimeOffset 값과 .Offset별도로 속성입니다.

  • .Net 프레임 워크에 내장 된 단방향 암시 적 변환이 DateTime있어 DateTimeOffset매개 변수 또는 변수에 전달할 수 있습니다 . 그렇게되면, .Kind중요 . UTC 종류를 전달하면 오프셋이 0으로 전달되지만 .Local또는 을 전달하면 local로.Unspecified 간주됩니다 . 프레임 워크는 기본적으로 "음, 당신은 나에게 달력 시간을 순간 시간으로 변환하라고 요청했지만, 이것이 어디에서 왔는지 전혀 모른다. 그래서 나는 단지 로컬 달력을 사용할 것이다." 다른 시간대의 컴퓨터에 지정되지 않은 컴퓨터 를로드하는 경우 큰 문제 입니다. (IMHO-예외가 발생해야하지만 그렇지 않습니다.)DateTime

뻔뻔한 플러그 :

많은 사람들이이 비유가 매우 귀중하다는 것을 나와 함께 나누었습니다. 그래서 나는 이것을 Pluralsight 코스, 날짜 및 시간 기초에 포함 시켰습니다 . "Calendar Time vs. Instantaneous Time"클립의 두 번째 모듈 인 "Context Matters"에서 카메라의 비유를 단계별로 살펴 봅니다.


4
@ZackJannsen DateTimeOffsetC #에 DATETIMEOFFSET있는 경우이를 SQL Server에 유지해야합니다 . DATETIME2또는 DATETIME(필요한 범위에 따라) 정규 DateTime값에 적합합니다. 예-시간대 + dto 또는 utc의 모든 페어링에서 현지 시간을 확인할 수 있습니다. 차이점은-각 해결마다 규칙을 항상 계산하고 싶습니까, 아니면 미리 계산하고 싶습니까? 많은 경우 (법적 문제가있는 경우도 있음) DTO가 더 나은 선택입니다.
Matt Johnson-Pint

3
@ZackJannsen 귀하의 질문의 두 번째 부분은 가능한 한 서버 측을 수행하는 것이 좋습니다. 자바 스크립트는 시간대 계산에 적합하지 않습니다. 그렇게해야하는 경우 다음 라이브러리 중 하나를 사용하십시오 . 그러나 서버 쪽이 가장 좋습니다. 더 자세한 질문이 있으면 새 SO 질문을 시작하십시오. 가능하면 답변 해 드리겠습니다. 감사.
Matt Johnson-Pint

4
@JoaoLeme-어디서 구했는지에 따라 다릅니다. DateTimeOffset.Now서버에서 말하면 실제로 서버의 오프셋을 얻습니다. 요점은 DateTimeOffset유형이 해당 오프셋을 유지할 수 있다는 것입니다. 클라이언트에서이를 쉽게 수행하여 서버로 전송하면 서버가 클라이언트의 오프셋을 알 수 있습니다.
Matt Johnson-Pint

8
카메라 비유를 정말 좋아합니다.
Sachin Kainth

2
예, 맞습니다. DTO가 (utc 시간, 오프셋) 쌍이 아닌 (로컬 시간, 오프셋) 쌍으로 저장되는 것을 제외하고. 즉, UTC로부터의 오프셋은 이미 현지 시간에 반영됩니다. utc로 다시 변환하려면 오프셋 부호를 반전시키고 현지 시간에 적용하십시오.
Matt Johnson-Pint

328

Microsoft에서 :

DateTimeOffset 값에 대한 이러한 사용은 DateTime 값에 대한 것보다 훨씬 일반적입니다. 결과적으로 DateTimeOffset은 응용 프로그램 개발을위한 기본 날짜 및 시간 유형으로 간주되어야합니다.

출처 : "DateTime, DateTimeOffset, TimeSpan 및 TimeZoneInfo 간 선택" , MSDN

DateTimeOffset애플리케이션이 특정 시점 (예 : 레코드가 생성 / 업데이트 된 시점)을 처리 할 때 거의 모든 것을 사용 합니다. 참고로 우리 DATETIMEOFFSET는 SQL Server 2008에서도 사용합니다.

나는 DateTime당신이 날짜 만, 시간 만 다루거나 일반적인 의미로 다룰 때 유용하다고 생각합니다. 예를 들어 매일 오전 7시에 알람을 울리 려는 경우 DST에 관계없이 오전 7시에 알람을 울리기를 원하기 때문에 알람을 DateTime이용하여 DateTimeKind에 저장할 수 있습니다 Unspecified. 그러나 알람 발생 이력을 나타내려면을 사용 DateTimeOffset합니다.

혼합 사용시 DateTimeOffset, DateTime특히 유형을 지정하고 비교할 때 주의하십시오 . 또한 비교할 때 시간대 오프셋을 무시 하므로 DateTime동일한 인스턴스 만 비교하십시오.DateTimeKindDateTime


146
허용되는 답변이 너무 길고 유추가 왜곡되어 훨씬 더 정확하고 간결한 답변 IMO입니다.
nexus는

10
나는이 답변이 마음에 들었다고 말할 뿐이다. 마지막 부분-보장조차 Kind동일하지만 비교가 잘못 될 수 있습니다. 양쪽 모두 DateTimeKind.Unspecified동일한 시간대에서 온 것을 실제로 모른다 면 . 양쪽이 모두 DateTimeKind.Local이면 대부분의 비교는 괜찮을 것입니다. 그러나 여전히 현지 시간대에서 한쪽이 모호하다는 오류가있을 수 있습니다. 실제로는 DateTimeKind.Utc비교 만 가능 하며 DateTimeOffset일반적으로 선호됩니다. (건배!)
Matt Johnson-Pint

1
+1 여기에 추가하겠습니다 : 선택한 DataType은 의도를 반영해야합니다. 어디서나 DateTimeOffset을 사용하지 마십시오. 오프셋이 계산 및 데이터베이스에서 읽기 / 지속 / 지속에 중요한 경우 DateTimeOffset을 사용하십시오. 중요하지 않은 경우 DateTime을 사용하면 오프셋에 베어링이 없어야하고 C # 코드가 실행되는 서버 / 기계의 로컬 성과 관련하여 시간이 유지되어야한다는 것을 DataType을 보면 알 수 있습니다.
MikeTeeVee

"하지만 알람 발생 이력을 나타내려면 DateTimeOffset을 사용합니다." 왜 이것이 생각하는지 설명하고 싶습니까? 이 페이지의 모든 정보를 읽음으로써 그 내용을 채울 수 있지만 읽기 쉬운 방식으로 그러한 정보를 제공 할 수도 있습니다. 이것은 매우 읽기 쉬운 대답입니다.
Barrosy

77

DateTime은 현지 시간과 UTC의 두 가지 시간 만 저장할 수 있습니다. 종류 속성은 어떤을 나타냅니다.

DateTimeOffset은 전 세계 어디에서나 현지 시간을 저장할 수있어이를 확장합니다. 또한 현지 시간과 UTC 사이 의 오프셋 을 저장합니다 . 해당 UTC 오프셋을 저장하기 위해 클래스에 추가 멤버를 추가하지 않으면 DateTime에서이를 수행 할 수없는 방법에 유의하십시오. 또는 UTC에서만 작동합니다. 그 자체로는 좋은 생각입니다.


33

DateTimeOffset말이 되는 곳 이 몇 군데 있습니다 . 하나는 반복되는 이벤트 및 일광 절약 시간제를 다룰 때입니다. 매일 오전 9시에 알람이 울리도록 설정하고 싶다고 가정 해 봅시다. "UTC로 저장, 현지 시간으로 표시"규칙을 사용 하면 일광 절약 시간 제가 적용 되는 다른 시간에 알람이 울립니다 .

아마도 다른 것이있을 수도 있지만 위의 예는 실제로 과거에 본 적이 있습니다 (이것은 DateTimeOffsetBCL을 추가하기 전이었습니다 . 당시의 솔루션은 현지 시간대로 시간을 명시 적으로 저장하고 저장하는 것이 었습니다. 그와 함께 시간대 정보 : 기본적으로 DateTimeOffset내부적 으로하는 일 ).


12
DateTimeOffset은 DST 문제를 해결하지 않습니다
JarrettV

2
TimeZoneInfo 클래스를 사용하면 DST에 대한 규칙이 적용됩니다. .net 3.5 이상인 경우 TimeZone 또는 TimeZoneInfo 클래스를 사용하여 시간대 오프셋과 함께 일광 절약 시간을 처리해야하는 날짜를 처리하십시오.
잭 얀센

1
예 (예 : 알람 응용 프로그램)의 좋은 예이지만 시간이 날짜보다 중요한 경우 응용 프로그램의 일정 데이터 구조 (예 : 발생 유형 = 매일 및 시간 = 09:00)로 별도로 저장해야합니다. 요점은 개발자가 어떤 유형의 날짜를 기록, 계산 또는 사용자에게 제공하는지 알고 있어야한다는 것입니다. 특히 우리는 인터넷을 표준으로 사용하고 소프트웨어를 작성할 수있는 큰 앱 스토어로 인터넷을 사용하는 경향이 있습니다. 사이드 노드로서 Microsoft가 별도의 날짜 및 시간 구조를 추가하고 싶습니다.
Tony Wall

3
Jarrett과 Zack의 의견 요약 : DateTimeOffset 만으로는 DST 문제를 처리하지 않지만 DateTimeOffset을 TimeZoneInfo와 함께 사용하면 처리됩니다. 종류가 Utc 인 DateTime과 다르지 않습니다. 두 경우 모두 내가 순간을 계획하고있는 캘린더의 시간대 (오프셋뿐만 아니라)를 알아야합니다. (필요한 경우 사용자 프로필에 저장하거나 클라이언트 (예 : Windows)에서 가져올 수 있습니다). 맞습니까?
Jeremy Cook

"DateTimeOffset이 적합한 곳이 몇 군데 있습니다." --- 논란의 여지가 있지만, 그렇지 않은 경우가 종종 있습니다.
Ronnie Overby

23

가장 중요한 차이점은 DateTime은 표준 시간대 정보를 저장하지 않지만 DateTimeOffset은 저장합니다.

DateTime은 UTC와 로컬을 구분하지만 명시적인 표준 시간대 오프셋은 없습니다. 어떤 종류의 직렬화 또는 변환을 수행하면 서버의 시간대가 사용됩니다. UTC 시간을 오프셋하기 위해 분을 추가하여 로컬 시간을 수동으로 생성하더라도 DateTime에 명시 적 오프셋이 없기 때문에 직렬화 단계에서 비트를 얻을 수 있습니다. 서버의 표준 시간대 오프셋을 사용하기 때문입니다.

예를 들어 Json.Net과 ISO 날짜 형식을 사용하여 Kind = Local로 DateTime 값을 직렬화하면 다음과 같은 문자열이 표시 2015-08-05T07:00:00-04됩니다. 마지막 부분 (-04)는 DateTime 또는 계산에 사용한 오프셋과 관련이 없습니다. 순전히 서버의 표준 시간대 오프셋입니다.

한편 DateTimeOffset에는 오프셋이 명시 적으로 포함됩니다. 시간대 이름을 포함하지 않을 수도 있지만 적어도 오프셋을 포함하고 직렬화하면 서버의 현지 시간이 아닌 값에 명시 적으로 포함 된 오프셋을 얻을 수 있습니다.


14
위의 모든 대답으로, 왜 아무도 당신의 단일 문장을 작성하여 귀찮게하지 않았는지 궁금합니다.The most important distinction is that DateTime does not store time zone information, while DateTimeOffset does.
Korayem

9
DateTimeOffset은 표준 시간대 정보를 저장하지 않습니다. "DateTime, DateTimeOffset, TimeSpan 및 TimeZoneInfo 사이의 선택"이라는 제목의 MS 문서는 "DateTimeOffset 값은 특정 시간대와 연결되어 있지 않지만 다양한 시간대에서 시작될 수 있습니다"라고 지정합니다. 즉, DateTimeOffset은 UTC와의 오프셋을 포함하는 표준 시간대 AWARE입니다. 이로 인해 모든 차이가 생겨 날짜 정보를 다루는 앱 개발을 처리 할 때 MS가 기본 클래스를 권장합니다. 당신이 진정 데이터에서 온 어떤 특정 시간대에 관심 있다면, 당신은 별도로 보존해야
stonedauwg

1
그렇습니다. 그러나 많은 곳에서 보았 듯이 + 또는-시간은 현재 시간대에 대해 아무 것도 말하지 않으며 결국 쓸모가 없습니다. 당신이해야 할 일에 따라, 당신은 Kind와 같은 날짜 시간을 저장할 수 있습니다.
Arwin

13

이 코드는 Microsoft의 모든 것을 설명합니다.

// Find difference between Date.Now and Date.UtcNow
  date1 = DateTime.Now;
  date2 = DateTime.UtcNow;
  difference = date1 - date2;
  Console.WriteLine("{0} - {1} = {2}", date1, date2, difference);

  // Find difference between Now and UtcNow using DateTimeOffset
  dateOffset1 = DateTimeOffset.Now;
  dateOffset2 = DateTimeOffset.UtcNow;
  difference = dateOffset1 - dateOffset2;
  Console.WriteLine("{0} - {1} = {2}", 
                    dateOffset1, dateOffset2, difference);
  // If run in the Pacific Standard time zone on 4/2/2007, the example
  // displays the following output to the console:
  //    4/2/2007 7:23:57 PM - 4/3/2007 2:23:57 AM = -07:00:00
  //    4/2/2007 7:23:57 PM -07:00 - 4/3/2007 2:23:57 AM +00:00 = 00:00:00

9

대부분의 답변은 훌륭하지만 자세한 내용을 보려면 MSDN 링크를 더 추가하는 것이 좋습니다.



7

주요 차이점은 현재 시간대 이외의 시간대에서 현지 시간으로 변환하는 DateTimeOffset데 사용할 수 있다는 TimeZoneInfo것입니다.

다른 시간대의 사용자가 액세스하는 서버 응용 프로그램 (예 : ASP.NET)에서 유용합니다.


3
@Bugeo Bugeo는 사실이지만 위험이 있습니다. 먼저 각각 "ToUniversalTime"을 호출하여 두 개의 DateTime을 비교할 수 있습니다. 비교에 DateTimeKind = Unspecified 값이 정확히 하나만 있으면 전략이 실패합니다. 이러한 실패 가능성은 현지 시간으로의 변환이 필요한 경우 DateTime보다 DateTimeOffset을 고려해야하는 이유입니다.
잭 얀센

위와 같이이 시나리오에서는 DateTimeOffset을 사용하는 것보다 TimeZoneId를 저장하는 것이 좋습니다. 결국 아무것도 의미하지 않습니다.
Arwin

2

내가 본 DateTimeOffset의 유일한 단점은 Microsoft가 XmlSerializer 클래스에서이를 지원하는 것입니다 (설계 상). 그러나 이후 XmlConvert 유틸리티 클래스에 추가되었습니다.

XmlConvert.ToDateTimeOffset

XmlConvert.ToString

나는 모든 이점 때문에 DateTimeOffset과 TimeZoneInfo를 사용한다고 말하면서 XML과 직렬화되거나 직렬화 될 수있는 엔티티를 만들 때 조심하십시오 (모든 비즈니스 객체).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.