Development Tip

내 DateTime을 UTC로 변환하는 데 문제가 있습니다.

yourdevel 2021. 1. 5. 19:42
반응형

내 DateTime을 UTC로 변환하는 데 문제가 있습니다.


데이터베이스에 모든 날짜를 UTC 형식으로 저장하고 있습니다. 사용자에게 시간대를 묻고 시간대를 사용하고 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"

나는 왜 이것을 얻고 있는지 모르겠습니다.

나는 두 가지 방법을 시도했다

 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 now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
 var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now, 
                                           ZoneId, TimeZoneInfo.Utc.Id);

이것은 또한 동일한 오류로 둘 다 실패했습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

편집이 작동합니까?

 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 @ Jon Skeet 편집

Ya 나는 단지 내가이 모든 것을 할 필요조차 없을 것이라고 생각하고 있었다. 시간 문제가 지금 나를 혼란스럽게하여 게시물이 명확하지 않을 수 있습니다. 나는 도대체 DateTime.Now가 무엇을 얻고 있는지 결코 알지 못합니다 (시간대를 다른 시간대로 변경하려고 시도했지만 계속 현지 시간을 얻었습니다).

이것이 제가 원하는 일입니다. 사용자가 사이트에 방문하면 경고가 추가되고 이제 utc로 저장됩니다 (이전 DateTime. 이제 누군가가 모든 것을 UTC로 저장하도록 제안했습니다).

따라서 사용자가 내 사이트에 오기 전에 내 호스팅 서버가 어디에 있는지에 따라 다음 날과 같을 수 있습니다. 따라서 경고가 8 월 30 일 (자신의 시간)에 표시된다고 말했지만 서버의 시차로 8 월 29 일에 올 수 있으며 경고가 표시됩니다.

그래서 저는 그것을 극복하고 싶었습니다. 이제 현지 시간을 저장 한 다음이 오프셋 항목을 사용해야할지 모르겠습니다. 또는 UTC 시간을 저장하십시오. 사용자가 여전히 현지 시간으로 생각하고있을 것이고 UTC가 실제로 어떻게 작동하는지 확신 할 수 없기 때문에 UTC 시간을 저장하는 것만으로는 여전히 잘못된 것일 수 있습니다.

편집 3

 var info = TimeZoneInfo.FindSystemTimeZoneById(id)

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

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);

산출:

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

당신은 설정할 필요 KindUnspecified다음과 같이 :

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

DateTimeKind.Local다른 시간대가 아니라 현지 시간대를 의미합니다. 그래서 오류가 발생했습니다.


dtb가 말했듯 DateTimeOffset이 특정 시간대로 날짜 / 시간을 저장 하려면 사용해야 합니다.

However, it's not at all clear from your post that you really need to. You only give examples using DateTime.Now and you say you're guessing that you're using the server time. What time do you actually want? If you just want the current time in UTC, use DateTime.UtcNow or DateTimeOffset.UtcNow. You don't need to know the time zone to know the current UTC time, precisely because it's universal.

If you're getting a date/time from the user in some other way, please give more information - that way we'll be able to work out what you need to do. Otherwise we're just guessing.


Everyone else's answer seems overly complex. I had a specific requirement and this worked fine for me:

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

Which outputs (from linqpad) what I expected:

12/20/2013 12:00:00 AM

12/20/2013 5:00:00 AM

Props to Slaks for the Unspecified kind tip. That's what I was missing. But all the talk about there being only two kinds of dates (local and UTC) just muddled the issue for me.

FYI -- the machine I ran this on was in Central Time Zone and DST was not in effect.


UTC is just a time zone that everyone agreed on as the standard time zone. Specifically, it's a time zone that contains London, England. EDIT: Note that it's not the exact same time zone; for example, UTC has no DST. (Thanks, Jon Skeet)

The only special thing about UTC is that it's much easier to use in .Net than any other time zone (DateTime.UtcNow, DateTime.ToUniversalTime, and other members).

Therefore, as others have mentioned, the best thing for you to do is store all dates in UTC within your database, then convert to the user's local time (by writing TimeZoneInfo.ConvertTime(time, usersTimeZone) before displaying.


If you want to be fancier, you can geolocate your users' IP addresses to automatically guess their time zones.

ReferenceURL : https://stackoverflow.com/questions/1354516/having-problems-with-converting-my-datetime-to-utc

반응형