When I check optionDate
's DateTime
property's DateTimeKind
value, I see Unspecified, even though I set dt's DateTimeKind
as UTC in below code. I expect optionDate
has a DateTime
which has a DateTimeKind
property set to UTC. Where am I wrong here?
var dt = new DateTime(Convert.ToInt32(optionDateInfo.dateTime.year),
Convert.ToInt32(optionDateInfo.dateTime.month), Convert.ToInt32(optionDateInfo.dateTime.day),
Convert.ToInt32(optionDateInfo.dateTime.hour), Convert.ToInt32(optionDateInfo.dateTime.minutes),
0, DateTimeKind.Utc);
var optionDate = new DateTimeOffset(dt);
CodePudding user response:
This is documented:
The value of the DateTime.Kind property of the returned DateTime object is DateTimeKind.Unspecified.
Note that a DateTimeOffset
does not have a "kind". It has a date, time, and offset. When you pass your DateTime
with kind Utc
, to it, it sets its offset to 0, and its date & time to the DateTime
given. At this point, your DateTimeKind
is "lost".
An offset of 0 does not necessarily mean that its kind is DateTimeKind.Utc
. It could be the local time in London, or somewhere in Africa too. So it can't give you a DateTime
with kind Utc
just because its offset is 0 either.
In addition, DateTime
being able to represent 3 kinds of things is already a questionable design, and if the DateTime
property can now return 3 different kinds of DateTime
depending on whether offset matches the local time, is UTC, or something else, that's just even worse.
Instead, it is designed to have 3 properties that give you DateTime
s with different kinds.
DateTime
gives you the date & time part of theDateTimeOffset
, with kindUnspecified
LocalDateTime
converts the date & time part of theDateTimeOffset
to the current timezone, and gives you aDateTime
with kindLocal
.UtcDateTime
converts the date & time part of theDateTimeOffset
to UTC, and gives you aDateTime
with kindUtc
.
If you want a DateTime
with kind Utc
, you should use that last one.
CodePudding user response:
Use the SpecifyKind
var myUtcZeroOffset = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
//If constructing a datetime offset to be not utc you can supply the offset instead
var myOffSetExplicitLocal = new DateTimeOffset(DateTime.Now, new TimeSpan(1, 0, 0));
var localDateTime = myOffSetExplicitLocal.DateTime;
var utcZeroOffSetDateTime = myOffSetExplicitLocal.UtcDateTime;
To make matters worse of cause it is a criticisable implementation from Microsoft, because Universally Coordinated Time is not a timezone but a notation, as per ISO 8601, so in fact toUTC as a concept is flawed because '2021-11-02T10:16:25.12345 01:00' is completely valid in the UTC format and UTC Zero offset, popularily called Zulu being the '2021-11-02T09:16:25.12345Z' equivalent which then gets datetimekind UTC is actually just in coordinated time the zero line around GMT latitude, but what makes it coordinated is the part which in 00:00 can be abbreviated to Z, so lots of stuff is done to mitigate the inherent conflict and with build servers and cloud providers the .Local is especially dubious, so I would recommend always to persist in ISO 8601 strings instead, unless you actually need to use them in with date operations in Your DB, in said case to name fields appropriate like DateTimeCreatedUtcZero column e.g. just my five cents of reason on the topic in general, hope it helps.