Reputation: 3629
It is my understanding that Azure Table Storage stores all datetime fields as UTC AKA Zulu Time.
Currently I am in the UK 11th May 2021 at 18:10. The current TimeZone here is BST (+1:00).
If I serialise that into JSON using the RoundtripKind option
string json = JsonConvert.SerializeObject(this.syncDates, Formatting.Indented, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind
});
It will be sent to my Web Api as
"2021-05-11T18:10:31.740582+01:00"
However when it is deserialised into the ASP NET Core controller method arguments it appears as a DateTime with DateTimeKind of Local but no longer has any Time Zone Info.
11/05/2021 18:10:31
I then write the Date into Azure Table Storage and it will be stored as UTC which is
11/05/2021 17:10:31
When I retreive the data from the web api to display it to the originating user or someone else who wants to look at their data, it is important to know the correct date and hour in relation to the user.
Should I be storing the originating Time offset\zone in a separate field and using that to convert the Date back out again?
Should I not be storing as a DateTime at all and using DateTimeOffset or is that pointless as Azure Table Storage will just convert the DTO to UTC as well?
Upvotes: 2
Views: 1884
Reputation: 241485
To preserve the offset during serialization/deserialization, yes - you should use the DateTimeOffset
type instead of DateTime
.
With regard to Azure Table Storage, while the SDKs support DateTimeOffset
, unfortunately the service itself does not. Thus saving a DateTimeOffset
value to Azure Storage will result in the equivalent UTC DateTime
being stored, as given by the .UtcDateTime
property of the DateTimeOffset
. When retrieving, you will have a DateTimeOffset
whose date and time are the equivalent UTC date and time, and the offset will be zero.
Thus, if you really need to keep track of the offset, you'll need to store that in a separate column, and combine the two in your controller upon return. The DateTimeOffset.ToOffset
method is the easiest way to do that correctly.
Alternatively, if you only need the date and time parts to be correct, you could fib a little and use a UTC DateTime
even if the value isn't actually in UTC. Just call DateTime.SpecifyKind
with DateTimeKind.Utc
on the way in, and with DateTimeKind.Unspecified
on the way out. You'll loose the offset, but if you don't need it anyway then this can work.
Upvotes: 1