Search code examples
c#datetimedatetimeoffset

DateTimeKind is Unspecified Even Though I Set it


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

Solution

  • This is documented:

    DateTimeOffset.DateTime

    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 DateTimes with different kinds.

    • DateTime gives you the date & time part of the DateTimeOffset, with kind Unspecified
    • LocalDateTime converts the date & time part of the DateTimeOffset to the current timezone, and gives you a DateTime with kind Local.
    • UtcDateTime converts the date & time part of the DateTimeOffset to UTC, and gives you a DateTime with kind Utc.

    If you want a DateTime with kind Utc, you should use that last one.