I am reading https://stackoverflow.com/a/6519330/1375882 and I understand that DateTime does not contain timezone. Indeed, there are no TimeZone member fields for DateTime. Yet there are ToLocalTime()
and ToUniversalTime()
members. E.g. I am testing my code in 2 timezone computer and it gives the trace (e.g. now it is 16.12.2021 16:17:23
in 2 timezone) and the code gives:
DateTime tmpNow = DateTime.UtcNow;
//16.12.2021 14:17:23 - this if fine, DateTime is UTC
tmp = tmpNow.ToString();
//16.12.2021 16:17:23
tmp = tmpNow.ToLocalTime().ToString();
//16.12.2021 14:17:23 - this is fine, DateTime is UTC
tmp = tmpNow.ToUniversalTime().ToString();
DateTime tmpCustom = new DateTime(2021, 12, 16, 16, 9, 10);
//16.12.2021 16:09:10 - this is strange, I assume that DateTime(...) is aware that it is
// executed in 2 and that 16:09:10 is in 2 and therefore ToString should be 14:09:10
tmp = tmpCustom.ToString();
//16.12.2021 18:09:10 - this is strange, see previous
tmp = tmpCustom.ToLocalTime().ToString();
//16.12.2021 14:09:10 - complete loss of understanding. If initialization has been to 14:09:10 UTC
// as I expected, then ToLocalTime.ToString had to bee 16:09:10, but ToLocalTime()... was 18:09:10
// hence ToUniversalTime() definitely had to be 2 hours before - 16:09:10.
tmp = tmpCustom.ToUniversalTime().ToString();
So, this is realy strange - the DateTime senses somehow whether it has been initialized with UTC or with simple combination of date-time-numbers. How to explain the DateTime code behavior and this depnedence on hidden timezone?
CodePudding user response:
All of this is in the docs, you just need to know where to look. Relevant here is the Kind
property. It's an enum: Local, Utc or Unspecified.
When Local, it assumes the timezone of the current culture. See the docs for the constructor you use:
The Kind property is initialized to DateTimeKind.Unspecified.
Then head over to ToUniversalTime()
:
the value returned by the ToUniversalTime method is determined by the Kind property of the current DateTime object
[...]
Unspecified: The current DateTime object is assumed to be a local time, and the conversion is performed as if Kind were Local.
So if you change your code to new DateTime(2021, 12, 16, 16, 9, 10, DateTimeKind.Local)
, the methods thereafter will work as expected - apart from your comment claiming you expect "14:09" there. That won't happen.