2009-08-30 5 views
47

모든 데이터베이스가 UTC 형식으로 저장됩니다. 사용자에게 자신의 시간대를 묻습니다. 시간대를 사용하고 싶습니다. 서버 시간은 UTC를 알아낼 시간입니다.내 DateTime을 UTC로 변환하는 데 문제가 있습니다.

일단 내가 검색하면 새롭게 변환 된 UTC 날짜를 사용하여 데이터베이스의 범위를 확인하고 싶습니다.

하지만 항상 예외가 발생합니다.

System.ArgumentException was unhandled by user code 
Message="The conversion could not be completed because the 
supplied DateTime did not have the Kind property set correctly. 
For example, when the Kind property is DateTimeKind.Local, 
the source time zone must be TimeZoneInfo.Local. 
Parameter name: sourceTimeZone" 

나는 왜 이것을 얻는 지 모른다.

나는이 그래서 난

DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now, 
              ZoneId, TimeZoneInfo.Utc.Id); 

피곤이 같은 오류와 함께 모두 실패 실패 2 가지 방법

TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(id); 
// I also tried DateTime.UtcNow 
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone); 

을 시도했다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

수정이 작업을 수행할까요?

DateTime localServerTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(id); 

var usersTime = TimeZoneInfo.ConvertTime(localServerTime, info); 

var utc = TimeZoneInfo.ConvertTimeToUtc(usersTime, userInfo); 

난 그냥도 모두이 작업을 수행 할 필요가 없습니다 수도에 대해 생각했다 존 소총

야 @ 편집 2. 시간의 문제로 인해 지금 당장 혼란 스럽기 때문에 게시물이 왜 그렇게 분명하지 않을 수 있습니다. 나는 도대체 DateTime.How가 (시간대를 다른 시간대로 변경하려고 시도했는데 내 로컬 시간대를 계속 유지하면서) 무엇을 얻는 지 결코 알지 못합니다.

이것은 내가하고 싶은 일입니다. 사용자가 사이트에 와서 일부 경고를 추가하고 이제는 utc (DateTime.Now가되기 전에 누군가가 UTC 모든 것을 저장하도록 제안 됨)로 저장됩니다.

그래서 사용자가 내 사이트에 방문하기 전에 내 호스팅 서버가 어디에 있던지 다음 날과 같을 수 있습니다. 따라서 경고가 8 월 30 일 (시간) 표시되지만 서버의 시간차가있는 것으로 알려졌다면 8 월 29 일에 경고 메시지가 표시됩니다.

그래서 나는 그걸 싸우고 싶었습니다. 그래서 지금 나는이 오프셋 된 것들을 사용하여 현지 시간을 저장해야하는지 확신 할 수 없습니까? 또는 UTC 시간 만 저장하십시오. UTC 시간을 저장하는 것만으로도 여전히 사용자가 현지 시간으로 생각할 것이므로 UTC가 실제로 작동하는 방식을 확신 할 수 없기 때문에 여전히 시간 차이가 발생할 수 있습니다.

EDIT3

var info = TimeZoneInfo.FindSystemTimeZoneById(id) 

DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(DataBaseUTCDate, 
              TimeZoneInfo.Utc, info); 
+0

'DateTime.Now.Kind'는 이미'Local'입니다; 당신은'SpecifyKind'를 호출 할 필요가 없습니다. – SLaks

+0

@ 편집 2 : UTC로 경고를 저장하고 내 대답에 표시된대로 사용자가 제공 한 시간대에 표시하십시오. – dtb

+0

그러면 어떻게 작동할까요? 나는 DateTime.UtcNow를 얻고 DB로부터 경보를 여과합니까? 발견 된 결과를 현지 시간으로 변환 하시겠습니까? – chobo2

답변

30

DateTime 구조는 두 개의 시간대 지원한다. 기계에서 실행

  • 로컬 시간대
  • 과 UTC한다.

구조는 DateTimeOffset입니다.

var info = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); 

DateTimeOffset localServerTime = DateTimeOffset.Now; 

DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(localServerTime, info); 

DateTimeOffset utc = localServerTime.ToUniversalTime(); 

Console.WriteLine("Local Time: {0}", localServerTime); 
Console.WriteLine("User's Time: {0}", usersTime); 
Console.WriteLine("UTC:   {0}", utc); 

출력 :

DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified); 
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone); 

DateTimeKind.Local 로컬 시간대에, 그리고 다른 시간대를 의미

Local Time: 30.08.2009 20:48:17 +02:00 
User's Time: 31.08.2009 03:48:17 +09:00 
UTC:   30.08.2009 18:48:17 +00:00 
+0

그게 효과가있는 것 같습니다. 시간이 혼란 스럽습니다. DAteTimeOffSet을 읽어야하고, 왜 작동하는지, 변환하는 것은 그렇지 않습니다. 하지만 난 그냥 DateTime 수 없습니다 궁금하네요 .UtcNow? 내가 그것을 할 때처럼 당신의 dateoffSet 물건 (서부 아프리카 시간 사용)을한다면 내 서버 시간을 utc 날짜로 변환합니다. 아니면 그들은 다를 것인가? – chobo2

+1

Jon Skeet이 말했듯이, 현재 시간을 UTC로 원하면'DateTime.UtcNow' 또는'DateTimeOffset.UtcNow' 만 사용하면됩니다. – dtb

+0

DateTime이 TimeZoneInfo 속성을 제공하지 않는 이유가 궁금하므로 시간대와 함께 날짜와 시간을 지정할 수 있습니다. – brighty

85

당신이처럼 KindUnspecified에 설정해야합니다. 그래서 당신은 오류가 발생했습니다.

+0

나는 이것을 시험 할 것이다. 내가 방금 편집 한 작업이 있습니까? 한 시간대에서 다른 시간대로 갈 때 UTC가 정확한 시간이었을 때 (서 아프리카 시간대가 약 10 분 정도) 꺼져있는 것처럼 보입니다. – chobo2

+0

흠. 그렇다면 올바른 시간대를 모르므로 작동하지 않습니까? 그럼 내가 잘못 utc 시간을 받고 있다고 생각하기 때문에 나는 여전히 무언가를 mssing입니다. – chobo2

+0

코드를 잘못 읽었습니다. 실제로 작동 할 것입니다. – SLaks

6

dtb가 말한 것처럼 특정 시간대와 함께 날짜/시간을 저장하려면 DateTimeOffset을 사용해야합니다.

그러나 실제로 필요한 게시물은 분명하지 않습니다. DateTime.Now만을 사용하는 예제를 제공하고 서버 시간을 사용하고 있다고이라고 생각하면 이라고 말합니다. 너 몇시에 실제로 원하는거야? 현재 시간을 UTC로 지정하려면 DateTime.UtcNow 또는 DateTimeOffset.UtcNow을 사용하십시오. 현재의 UTC 시간을 알기 위해서는 시간대를 알 필요가 없습니다. 왜냐하면 그것이 보편적이기 때문입니다.

다른 방법으로 사용자로부터 날짜/시간을 받고있는 경우 자세한 정보를 알려주십시오. 그러면 Google에서 사용자가해야 할 일을 처리 할 수 ​​있습니다. 그렇지 않으면 우리는 단지 짐작하고 있습니다.

+0

내 원래의 게시물을 참조하십시오 Edit2 – chobo2

2

UTC은 모든 사람들이 표준 시간대로 합의한 표준 시간대입니다. 구체적으로 영국의 런던을 포함하는 시간대입니다. EDIT : 정확히 동일한 시간대가 아닙니다. 예를 들어 UTC에는 DST가 없습니다. (Thanks, Jon Skeet)

UTC에 관한 유일한 특별한 점은 다른 표준 시간대 (DateTime.UtcNow, DateTime.ToUniversalTime 및 다른 구성원)보다 .Net에서 사용하는 것이 훨씬 쉽다는 점입니다. 다른 언급이

따라서, 당신이해야 할 가장 좋은 방법은 표시하기 전에 TimeZoneInfo.ConvertTime(time, usersTimeZone)를 작성하여 사용자의 로컬 시간 (로 변환 한 후, 데이터베이스 내에서 UTC의 모든 날짜를 저장합니다.


하는 경우 당신은 애호가가되고 싶어요, 당신은 자동으로 시간대를 추측하는 사용자의 IP 주소를 geolocate

+0

그건 미래 버전 롤 것입니다. 기초를 먼저 얻으십시오. – chobo2

+0

그러면 지금 무엇을 알고 싶습니까? – SLaks

+0

그래서 이것은 다른 시간을주지 않을 것입니다. 먼저 UTC에 의한 모든 경고를 얻은 후 발견 된 현지 시간으로 변경하면 경고가 누락되지 않습니다. 그들의 것 같이되지 않을 것입니다 일부는 어디서 어떻게 몇 분 또는 무언가에 의해 어떻게 떨어져? – chobo2

5

모두 다른 사람의 대답은 지나치게 복잡 보인다 나는 특정 요구 사항을 가지고 이것은 나를 위해 잘 작동 :..

,536,913,632

2013년 12월 20일 오전 12시 0분 0초

2013년 12월 20일 오전 5시 0분 0초

소품 : 내가 기대했던 (linqpad에서) 출력 10

void Main() 
{ 
    var startDate = DateTime.Today; 
    var StartDateUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.SpecifyKind(startDate.Date, DateTimeKind.Unspecified), "Eastern Standard Time", "UTC"); 
    startDate.Dump(); 
    StartDateUtc.Dump(); 
} 

Unspecified 종류 팁에 대한 슬랙에. 그게 내가 놓친거야. 그러나 단지 2 가지 종류의 날짜 (현지 및 UTC) 만 있다는 모든 이야기는 저를 위해 그 문제를 혼란스럽게 만들었습니다.

FYI -이 컴퓨터를 실행 한 시간은 중부 표준 시간대이며 DST가 적용되지 않았습니다.

관련 문제