Reputation: 55
It must be something really simple and perhaps I am just not seeing it. Have been looking at this for the last couple of days and am out of things to try.
Dev Env. - Visual Studio 2019, C#, .net Core 3.1 - deploying to Azure
We have an Azure function that processes a JSON payload and stores it into Cosmos DB. One of the fields in the JSON is a Datetime field for which the requirement is to store in local time with a UTC offset.
For ex: 2022-05-07T04:05:00-04:00
This is backed by a POCO class where I have tried to define this field as both DateTime, DateTimeOffset, and even String but having issues when this is saved into Cosmos DB as a document. When running the Azure function locally, it works perfectly and I can check in Cosmos and see the above value saved (I am in EST/EDT timezone).
But when this function is deployed into Azure (US East 2), it ends up saving this as below: 2022-05-07T08:05:00+00:00 (i.e. saves it as UTC with 00:00 offset).
I am using Newtonsoft to process JSON objects and did see a lot of threads about Datetime and Datetimeoffset issues but even with those suggestions, I haven't had any success.
I set verbose logging and just before calling DocumentClient.CreateDocumentAsync, the value is still correct. But once it is saved, it changes to UTC. Same code when run locally (and saving to the exact same Cosmos DB container) saves it correctly.
Edit: Setting WEBSITE_TIME_ZONE value on the function app forces the data to save correctly, but this just means that instead of UTC it will save it in the (for ex.) Eastern Standard Time instead. The intention of this field is to hold the local time with the correct UTC offset.
Edit 2: Seeing some odd behavior that leads me to believe it could be something in the way data is structured?
When the "obj" is sent like below:
JObject obj = JObject.FromObject(new {doc=document }, new Newtonsoft.Json.JsonSerializer(){ DateParseHandling = DateParseHandling.None});
await client.CreateDocumentAsync(uri, obj);
The date is saved correctly! But this introduces a new parent node (doc) that causes issues with other parts of the system.
But when it is like below:
JObject obj = JObject.FromObject(document, new Newtonsoft.Json.JsonSerializer(){ DateParseHandling = DateParseHandling.None});
await client.CreateDocumentAsync(uri, obj);
OR
await client.CreateDocumentAsync(uri, document); // Without re-creating the JObject
The date is saved as UTC!
Upvotes: 1
Views: 959
Reputation: 241778
Per this doc, Azure CosmosDB will expect your values to be stored as UTC, whether in a DateTime
, or in a DateTimeOffset
. This is so the values are still ordered correctly when lexicographically sorted.
Thus, if you need to persist the offset, consider storing it in a separate field in your data model.
For example:
DateTime UtcDateTime {get; set;}
TimeSpan Offset {get; set;}
If needed, you can then compute the original DateTimeOffset
from those values.
DateTimeOffset DateTimeOffset =>
new DateTimeOffset(UtcDateTime, TimeSpan.Zero).ToOffset(Offset);
Upvotes: 1