2

When I deserialize this json string "2020-10-05T07:29:00+00:00" on my local pc to a DateTime object it ends up as 2020-10-05 09:29, where it should be 07:29. The date is specified as local (+00:00) so I don't understand where the extra two hours come from. I tried looking at this question Datetime timezone deserialization but converting the date by using .ToLocalTime() does nothing.

The context is a large json string with airports from an external API with many datetimes, some are UTC some are local times. I need to find the simplest way to deserialize the string which will produce the correct datetimes.

Note that the local time could be anywhere in the world, so it should not depend on the server that runs the application.

Here's a code example using NewtonSoft.Json to deserialize:

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

This is my output in my timezone (UTC +2 DaylightSavingTime):

UTC:05-10-2020 05:29:00 (Utc). LOC:05-10-2020 09:29:00 (Local) Conversion failed

Here is a dotnet fiddle https://dotnetfiddle.net/uHLdAh This produces the correct output since the server probably runs GMT.

2
  • "The date is specified as local (+00:00)" - no, that's specifying it as "with a 0 offset from UTC", i.e. that it's equivalent to UTC. If the offset is actually 2 hours, then the string should include +02:00. Commented Nov 27, 2020 at 8:00
  • "Note that the local time could be anywhere in the world, so it should not depend on the server that runs the application." I'd strongly suggest using DateTimeOffset. The values you're receiving are effectively DateTimeOffset values anyway (a local time and a UTC offset) so using DateTime instead just loses information and complicates things. (I'd really suggest using my Noda Time library instead to make things clearer, but that's a slightly different matter.) Commented Nov 27, 2020 at 8:30

2 Answers 2

1

The problem is that "2020-10-05T07:29:00+00:00" isn't local time, it is interpreted as an UTC time with 0 hours offset. And, when you run it on your machine it adds the offset of your current timezone, i.e. +02:00h.

For example, the time is now 08:36 and my timezone is CET. If I were to create a DateTimeOffset object in UTC it would say 2020-11-27T06:36:00+02:00.

So, running the following code yields different results depending on the time zone of the executing machine:

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

Output when running on dotnetfiddle.net:

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

Output when running on my local machine:

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

You have to determine if your input is given in UTC time with a proper offset of 0, or if it is in "local" time, with a faulty offset. Then you should have to create a DateTimeOffset object specifying the timezone that the new datetime object should have.

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

Which yields the following output:

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

You now has a DateTimeOffset object behaving as expected.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. The +00:00 is in fact interpreted as local time as you can see from my output. You are correct that if I deserialize the json string to DateTimeOffset objects I will get the correct time. I can't do that because I'm relying on a service contract and prefer not to create a new contract myself. The local time can in fact represent the local time in Thailand for that matter, so it should not be dependant on my machine. I just want the datetime which is stated in the json string without any modifications.
The problem is that the time "2020-10-05T07:29:00+00:00" is not a local time if you live in another timezone than GMT (0° (Prime Meridian)). If you want to represent the time 07:29 in Thailand local time in a YYYY-MM-DDTHH:MM:SS+nn:nn format it would be "2020-10-05T00:29:00+07:00", which would result in "2020-10-05T07:29:00" when printing it as local time.
0

The solution to the problem proved to be a simple one. Just assume all times are UTC. This fixes all issues in the conversion.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.