JSON 문자열을 현지 시간대의 .NET DateTime으로 역 직렬화하면 2 시간이 추가됩니다.

Nov 27 2020

이 json 문자열 "2020-10-05T07 : 29 : 00 + 00 : 00"을 로컬 PC에서 DateTime 개체로 역 직렬화하면 2020-10-05 09:29로 끝나며 여기서 07:29 여야합니다. 날짜는 현지 (+00 : 00)로 지정되어 있으므로 추가 2 시간이 어디에서 오는지 이해할 수 없습니다. 이 질문 Datetime 시간대 역 직렬화를 시도했지만 .ToLocalTime ()을 사용하여 날짜를 변환하면 아무것도하지 않습니다.

컨텍스트는 많은 datetime이있는 외부 API의 공항이있는 큰 json 문자열이며 일부는 UTC이며 일부는 현지 시간입니다. 올바른 날짜 시간을 생성하는 문자열을 역 직렬화하는 가장 간단한 방법을 찾아야합니다.

현지 시간은 전 세계 어디에나있을 수 있으므로 응용 프로그램을 실행하는 서버에 의존해서는 안됩니다.

다음은 NewtonSoft.Json을 사용하여 역 직렬화하는 코드 예제입니다.

static void Main(string[] args)
    {
        var json =
            "{\"UTC\": \"2020-10-05T05:29:00Z\",\"Local\": \"2020-10-05T07:29:00+00:00\" }";
        var expected = new DateTime(2020,10,5,7,29,0);
        var foo = JsonConvert.DeserializeObject<CustomTime>(json);
        Console.WriteLine($"UTC:{foo.UTC} ({foo.UTC.Kind}).\r\nLOC:{foo.Local} ({foo.Local.Kind})");
        System.Console.WriteLine(foo.Local.Equals(expected) ? "All good" : "Conversion failed");
    }

public sealed class CustomTime
{
    public DateTime UTC { get; set; }
    public DateTime Local { get; set; }
}

이것은 내 시간대 (UTC +2 DaylightSavingTime)의 출력입니다.

UTC : 05-10-2020 05:29:00 (Utc). LOC : 05-10-2020 09:29:00 (로컬) 변환 실패

여기 dotnet 바이올린이 있습니다 https://dotnetfiddle.net/uHLdAh 이는 서버가 GMT를 실행하기 때문에 올바른 출력을 생성합니다.

답변

1 iikkoo Nov 27 2020 at 14:56

문제는 "2020-10-05T07 : 29 : 00 + 00 : 00"이 현지 시간이 아니라 0 시간 오프셋이있는 UTC 시간으로 해석된다는 것입니다. 그리고 컴퓨터에서 실행하면 현재 시간대의 오프셋, 즉 +02 : 00h가 추가됩니다.

예를 들어 현재 시간은 08:36이고 내 시간대는 CET입니다. UTC로 DateTimeOffset 객체를 생성하면 2020-11-27T06 : 36 : 00 + 02 : 00이됩니다.

따라서 다음 코드를 실행하면 실행중인 컴퓨터의 시간대에 따라 다른 결과가 생성됩니다.

 // Current time
 dto = DateTimeOffset.Now;
 Console.WriteLine(dto.LocalDateTime);
 // UTC time
 dto = DateTimeOffset.UtcNow;
 Console.WriteLine(dto.LocalDateTime);

dotnetfiddle.net에서 실행할 때 출력 :

3/11/2007 10:30:00 AM
3/11/2007 9:30:00 AM

내 로컬 컴퓨터에서 실행할 때 출력 :

2020-11-27 08:54:09
2020-11-27 08:54:09

입력이 올바른 오프셋 0을 사용하여 UTC 시간으로 제공되는지 또는 잘못된 오프셋이있는 "현지"시간인지 확인해야합니다. 그런 다음 새 datetime 개체가 가져야하는 시간대를 지정하는 DateTimeOffset 개체를 만들어야합니다.

var dto = new DateTimeOffset(2020,10,5,7,29,0, new TimeSpan(2, 0, 0));
Console.WriteLine(dto);
Console.WriteLine(dto.LocalDateTime.Kind);
Console.WriteLine(dto.UtcDateTime);
Console.WriteLine(dto.UtcDateTime.Kind);

다음과 같은 출력이 생성됩니다.

2020-10-05 07:29:00 +02:00
Local
2020-10-05 05:29:00
Utc

이제 예상대로 작동하는 DateTimeOffset 개체가 있습니다.

MRaymaker Nov 27 2020 at 19:41

문제에 대한 해결책은 간단한 것으로 판명되었습니다. 모든 시간이 UTC라고 가정하십시오. 이것은 변환의 모든 문제를 해결합니다.

var foo = JsonConvert.DeserializeObject<CustomTime>(json, new JsonSerializerSettings
{
   DateTimeZoneHandling = DateTimeZoneHandling.Utc
});