UTC / GMT 시간을 현지 시간으로 변환


301

웹 서비스 클라이언트를위한 C # 응용 프로그램을 개발 중입니다. 이것은 Windows XP PC에서 실행됩니다.

웹 서비스가 리턴하는 필드 중 하나는 DateTime 필드입니다. 서버는 GMT 형식의 필드, 즉 끝에 "Z"를 반환합니다.

그러나 .NET은 일종의 암시 적 변환을 수행하는 것으로 보이며 시간은 항상 12 시간입니다.

다음 코드 샘플은 12 시간의 차이가 사라졌지 만 NZ 일광 절약 시간을 허용하지 않는다는 점에서이 문제를 어느 정도 해결합니다.

CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            

따라 이 날짜 사이트 :

UTC / GMT 오프셋

표준 시간대 : UTC / GMT +12 시간
일광 절약 시간 : +1 시간
현재 시간대 오프셋 : UTC / GMT +13 시간

여분의 시간을 어떻게 조정합니까? 프로그래밍 방식으로 수행 할 수 있습니까? 아니면 PC에서 어떤 설정입니까?


2
Z시간은 UTC하지 GMT을 의미합니다. 이 둘은 최대 0.9 초까지 다를 수 있습니다.
mc0e

답변:


374

같은 문자열의 경우 2012-09-19 01:27:30.000, DateTime.Parse날짜와 시간에서 어떤 시간대 말할 수 없다.

DateTime종류의 세 가지 시간대 옵션 중 하나를 가질 수 속성을 :

  • 불특정
  • 현지
  • Utc

참고 UTC 또는 현지 시간대 이외의 날짜 / 시간을 나타내려면을 사용해야합니다 DateTimeOffset.


따라서 질문의 코드는 다음과 같습니다.

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

당신은 그것이 어떤 종류인지 알고 있다고 말하십시오.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

이제 시스템이 UTC 시간을 알면 다음을 호출하면됩니다 ToLocalTime.

DateTime dt = convertedDate.ToLocalTime();

필요한 결과를 얻을 수 있습니다.


19
종류를 지정하는 또 다른 방법 :DateTime convertedTime = new DateTime(DateTime.Parse(dateStr).Ticks), DateTimeKind.Utc);
Brad

ToLocalTime () 아닌가요? @ 브래드-당신의 parens가 일치하지 않습니다.
TrueWill

2
이 솔루션은 일광 절약 시간제를 설명합니까? 시험 해보면 한 시간은 쉬어 요.
밥 혼

7
변화의 단계 Kind의이 DateTime에서 Unspecified로는 UTC불필요하다. Unspecified로 가정 UTC의 목적 ToLocalTime: msdn.microsoft.com/en-us/library/...
CJ7

16
@ CJ7 : 그렇습니다. 그러나 명시적인 것은 코드를 유지해야하는 다른 개발자에게 특히 도움이됩니다.
Ryan

121

.NET 3.5 인 경우 System.TimeZoneInfo 클래스를 사용하는 방법을 살펴 보겠습니다. http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx를 참조 하십시오 . 일광 절약 시간제 변경 사항을 올바르게 고려해야합니다.

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime();

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);

자신의 시간대 (이 경우 en-NZ)에서 작업하는 경우 TimeZoneInfo를 처리 할 필요가 없습니다. 불필요한 복잡성입니다. 자세한 내용은 내 답변을 참조하십시오.
Drew Noakes

11
그리고 누군가가 필요하다면, 여기 내가 TimeZoneInfo.FindSystemTimeZoneById에 대해 찾은 시간대 목록이 있습니다. – codeproject.com/Messages/3867850/…
nikib3ro

훌륭한! 이 게시물 Dan에 감사드립니다. 3 일 동안이 수정 프로그램을 찾고있었습니다.
Kevin Moore

58
TimeZone.CurrentTimeZone.ToLocalTime(date);

8
이것은 시스템이 변환되는 날짜가 UTC임을 알고있는 경우에만 작동합니다. 내 대답을 참조하십시오.
Drew Noakes

1
그러나 UTC가 기본값입니까? 따라서 CJ7의 답변 에서처럼 "지정되지 않은"것으로 작동합니다.
NickG

25

DateTime객체는이 Kind의를 Unspecified의 목적을 위해 기본적 ToLocalTime으로 간주됩니다 UTC.

Unspecified DateTime객체 의 현지 시간을 얻으려면 다음 을 수행하면됩니다.

convertedDate.ToLocalTime();

변화의 단계 Kind의이 DateTime에서 Unspecified로는 UTC불필요하다. Unspecified로 가정 UTC의 목적을 위해 ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx


6
그리고 그 반대의 경우 : convertedDate.FromLocalTime();로 변환됩니다 UTC.
R. Schreurs

16

나는 이것이 더 오래된 질문이라는 것을 알고 있지만 비슷한 상황에 빠졌으며 나 자신을 포함하여 미래의 검색 자에게 찾은 것을 공유하고 싶었습니다. :)

DateTime.Parse()까다로울 수 있습니다- 예를 들어 여기 를 참조 하십시오 .

DateTime웹 서비스 또는 알려진 형식의 다른 소스에서 오는 경우 다음과 같은 것을 고려할 수 있습니다.

DateTime.ParseExact(dateString, 
                   "MM/dd/yyyy HH:mm:ss", 
                   CultureInfo.InvariantCulture, 
                   DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)

또는 더 나은

DateTime.TryParseExact(...)

AssumeUniversal플래그는 날짜 / 시간이 이미 UTC 것을 파서를 알려줍니다; 의 조합 AssumeUniversalAdjustToUniversal는 기본적으로 수행하려고 할 것 "로컬"시간에 결과를 변환하지를 알려줍니다. (어쨌든 비즈니스 / 응용 프로그램 / 서비스 계층에서 UTC를 독점적으로 처리하려고 시도하지만 현지 시간으로의 전환을 우회하면 테스트에서 50 % 이상 속도가 빨라집니다 (아래 참조).

우리가 전에 한 일은 다음과 같습니다.

DateTime.Parse(dateString, new CultureInfo("en-US"))

앱을 프로파일 링 한 결과 DateTime.Parse가 CPU 사용률의 상당 부분을 차지한다는 것을 알았습니다. (우연히도 CultureInfo생성자는 CPU 사용량에 크게 기여 하지 않았습니다 .)

그래서 다양한 방법으로 날짜 / 시간 문자열을 10000 번 구문 분석하도록 콘솔 앱을 설정했습니다. 결론 :
Parse()10 초
ParseExact()(로컬로 변환) 20-45 ms
ParseExact()(로컬로 변환하지 않음) 10-15 ms
... 및 예, 결과 Parse()초 단위 이지만 다른 결과는 밀리 초 입니다.


14

일반적인주의 사항을 추가하고 싶습니다.

컴퓨터 내부 시계에서 현재 시간을 가져 와서 디스플레이 또는 보고서에 날짜 / 시간을 입력하면 모든 것이 정상입니다. 그러나 나중에 참조하기 위해 날짜 / 시간 정보를 저장 하거나 날짜 / 시간을 계산하는 경우주의하십시오!

2007 년 12 월 20 일 15:00 UTC에 호놀룰루에 유람선이 도착했다고 가정 해 봅시다. 그리고 당신은 그것이 어떤 현지 시간인지 알고 싶어합니다.
1. 아마도 적어도 세 곳의 '로컬'이 관련되어있을 것입니다. 로컬은 호놀룰루를 의미하거나 컴퓨터가있는 위치를 의미하거나 고객이있는 위치를 의미 할 수 있습니다.
2. 내장 함수를 사용하여 변환을 수행하면 잘못되었을 수 있습니다. 일광 절약 시간 제가 현재 컴퓨터에는 유효하지만 12 월에는 유효하지 않기 때문입니다. 그러나 Windows는 이것을 알지 못합니다 ... 일광 절약 시간 제가 현재 유효한지 여부를 결정하는 플래그는 하나뿐입니다. 현재 시행 중이라면 12 월의 날짜에도 한 시간을 더할 수 있습니다.
삼.일광 절약 시간제는 다양한 정치적 세분에서 다르게 구현되거나 전혀 구현되지 않습니다. 국가가 특정 날짜에 변경되어 다른 국가도 변경 될 것이라고 생각하지 마십시오.


6
실제로, # 2는 전적으로 정확하지 않습니다. 정보가 설치 및 업데이트되었는지 컴퓨터가 알 수있는 모든 시간대에 DST에 대한 규칙이 있습니다. 많은 영역에서 이러한 규칙은 고정되어 있습니다. 다른 사람들은 "동적 DST"를 구현합니다. 브라질은 이것에 대한 나의 애완 동물입니다. 그러나 요약하자면, 12 월에 현지 시간이 DST가 될 경우, 현재와 그 사이의 법률 변경 사항이 없다고 가정 할 때, 귀하의 코우 터는 운동 할 수 있습니다.
Roger Willcocks 2018

브라질에 거주하지 않더라도 DST는 정치인들이 몇 년 전에 미국에서 한 것처럼 언제든지 변경할 수 있다는 점에서 "동적"입니다. 대부분의 소프트웨어는 향후 사용을 염두에두고 작성되었으므로 어떤 DST 규칙이 적용되는지 알 수있는 실제적이고 예측 가능하거나 이론적 인 방법이 없다는 것을 인식하는 것이 중요합니다. 가까이 갈 수는 있지만 완벽 함을 포기하면 좌절감을 느끼실 수 있습니다.
DaveWalley


5

DateTime 객체가 이미 있고 UTC 또는 로컬인지 확실하지 않은 경우, 객체의 메서드를 직접 사용하기가 쉽습니다.

DateTime convertedDate = DateTime.Parse(date);
DateTime localDate = convertedDate.ToLocalTime();

여분의 시간을 어떻게 조정합니까?

.net이 로컬 PC 설정을 사용하지 않는 한. http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx에 대해 읽었습니다 .

외관상 코드는 다음과 같습니다.

DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year );

위에서 언급했듯이 서버의 시간대 설정을 다시 확인하십시오. 인터넷상의 IIS 변경에 안전하게 영향을 미치는 방법에 대한 기사가 있습니다.


날짜가 어떤 종류인지 (지역 / utc / 지정되지 않은) 시스템에 알려 주면 시스템은 이러한 복잡성을 처리합니다.
Drew Noakes

2

Dana의 제안에 대한 답변 :

코드 샘플은 다음과 같습니다.

string date = "Web service date"..ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate);

원래 날짜는 08/08/08입니다. 종류는 UTC였습니다.

"convertedDate"와 "dt"는 동일합니다.

21/08/08 10:00:26; 종류는 지역이었다


이에 대한 설명은 내 답변을 참조하십시오.
Drew Noakes

1

DataColumn의 DateType 필드가 로컬로 설정되어 있기 때문에 자동으로 변경되는 유선 (웹 서비스에서 클라이언트로)을 가로 질러 데이터 세트에 문제가 있습니다. 데이터 세트를 푸시하는 경우 DateType이 무엇인지 확인하십시오.

변경하지 않으려면 지정되지 않음으로 설정하십시오.


1

트위터 API (상태에서 creed_at 필드)를 통해 반환되는 UTC 날짜에 문제가 있기 때문에이 질문을 보았습니다. DateTime으로 변환해야합니다. 이 페이지의 답변에있는 답변 / 코드 샘플 중 어느 것도 "문자열이 유효한 DateTime으로 인식되지 않았습니다"오류가 발생하는 것을 막기에 충분하지 않았습니다 (그러나 SO에서 정답을 찾는 것이 가장 가깝습니다)

이 링크를 게시하면 다른 사람에게 도움이됩니다. 필요한 답변은 다음 블로그 게시물에서 찾을 수 있습니다 . -기본적으로 DateTime.Parse 대신 형식 문자열과 함께 DateTime.ParseExact를 사용하십시오.

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