Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DateTimeOffset Formatting is not working #3008

Closed
HankRocha opened this issue Jan 10, 2025 · 9 comments
Closed

DateTimeOffset Formatting is not working #3008

HankRocha opened this issue Jan 10, 2025 · 9 comments

Comments

@HankRocha
Copy link

I tried to use the setting described here https://www.newtonsoft.com/json/help/html/SerializeDateTimeZoneHandling.htm
but it does't work :(

var jSetting = new JsonSerializerSettings();
jSetting.ContractResolver = new CamelCasePropertyNamesContractResolver();
jSetting.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
var jsonObj = JsonConvert.SerializeObject(objList, jSetting);

in the result all datetime include the offset "+00:00"

@elgonzo
Copy link

elgonzo commented Jan 11, 2025

It is working as intended. You just need to pay utmost attention to the details here.

EDIT: To future readers, DateTimeZoneHandling does not seem to apply to serialization of DateTimeOffset values. Specifically, despite the documentation linked to in the report above suggesting that DateTimeZoneHandling applies to both DateTime and DateTimeOffset, DateTimeZoneHandling.Utc will not convert non-UTC DateTimeOffset values to UTC-base-time based values prior to serialization.

The example code you linked to is a red herring. Note how the example code uses DateTime instances. But you are using DateTimeOffset instances. This detail is very important.

To understand, pay attention to the JsonSerializerSettings.DateFormatString setting: https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonSerializerSettings_DateFormatString.htm.

Note how the default value for this setting use the K custom date and time format specifier. As per documentation for K https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings#KSpecifier:

For DateTimeOffset values, the "K" format specifier is equivalent to the "zzz" format specifier, and produces a result string containing the DateTimeOffset value's offset from UTC.

(Also see the table with K examples for DateTime and DateTimeOffset here: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings)

So, basically, as per the K format specifier, UTC DateTimes will be stringified/serialized with a "Z" suffix, whereas UTC DateTimeOffsets will be stringified/serialized with a "+00:00" offset.

(Disclaimer: I am not author/maintainer of this library. I am just a fellow, mostly former user of this library.)

@HankRocha
Copy link
Author

HankRocha commented Jan 13, 2025

Thanks for your reply.
So the first "help" link incorrectly says it applies to DateTimeOffset, right?
But should it? That is, if I have a DateTimeOffset and I want the result as a DateTime string. (that's what I wanted to do initially)

@elgonzo
Copy link

elgonzo commented Jan 13, 2025

So the first "help" link incorrectly says it applies to DateTimeOffset, right?

No. The first "help" link correctly says it applies to DateTimeOffset.

You gotta really pay attention. JsonSerializerSettings.DateFormatString applies to both DateTime and DateTimeOffset.

The K format specifier also applies to both DateTime and DateTimeOffset. It's just that K has a different effect on DateTime and DateTimeOffset, as i tried to explain in my last comment.

@HankRocha
Copy link
Author

I'm sorry.
When I said the first link I was referring to the one in the question, the one that refers to DateTimeZoneHandling

@elgonzo
Copy link

elgonzo commented Jan 13, 2025

When I said the first link I was referring to the one in the question, the one that refers to DateTimeZoneHandling

"+00:00" is UTC base time. So why exactly would you believe that DateTimeZoneHandling.Utc doesn't apply to DateTimeOffset's, despite you seeing "+00:00"?

EDIT: To future readers, DateTimeZoneHandling.Utc does indeed not apply to serialization of DateTimeOffset values.

@HankRocha
Copy link
Author

my english is not very good, so i'll try to explain
when I have this setting:
DateTimeZoneHandling = DateTimeZoneHandling.Utc

I was expecting, the result string be formatted as UTC.
For example,
"2013-01-21T01:00:00+01:00" -> "2013-01-21T00:00:00Z"
(Suppose it should do the convertion or something like that)

@elgonzo
Copy link

elgonzo commented Jan 13, 2025

If it is important to you to stringify/serialize UTC DateTimeOffset values with a "Z" suffix instead of "+00:00", you will have to obtain the respective DateTime value from the DateTimeOffset value (please look up the DateTimeOffset documentation if you don't know already how to convert between DateTimeOffset and DateTime) and stringify/serialize this DateTime value instead.

With respect to Newtonsoft.Json, you have to do this in the WriteJson method of a custom JsonConverter which you will have to write.

If you also need to deserialize json date/time strings with a "Z" suffix into DateTimeOffset values, you might perhaps also need to implement the ReadJson method of the custom JsonConverter accordingly, as DateTimeOffset.Parse might perhaps not understand the "Z" suffix. But i am not entirely sure about it, so i'll leave it to you to figure out when necessary...

(Why the creators of the .NET Framework many, many years ago decided to string-format UTC time zone for DateTimeOffset as "+00:00" but for DateTime as "Z", i don't know. But i suspect it's because DateTimeOffset technically isn't based on time zone information, only time offsets from UTC base time, so i wager it makes sense regarding consistent behavior for DateTimeOffset to not stringify a time zone identifier but UTC time offsets only.)

@HankRocha
Copy link
Author

I appreciate your time and patience. You are the best.

@elgonzo
Copy link

elgonzo commented Jan 13, 2025

Oh, one major correction.

You were right regarding the documentation at https://www.newtonsoft.com/json/help/html/SerializeDateTimeZoneHandling.htm being not correct.

DateTimeZoneHandling does indeed not apply to DateTimeOffsets, as you already suspected.

Using DateTimeZoneHandling.Utc won't convert any non-UTC DateTimeOffset value to the equivalent UTC time (so keeping any non-zero time offset in the serialized result).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants