My application is hosted on Windows Azure, which has all servers set to UTC.
I need to know when any given DateTime
is subject to daylight savings time. For simplicity, we can assume that my users are all in the UK (so using Greenwich Mean Time).
The code I am using to convert my DateTime
objects is
public static DateTime UtcToUserTimeZone(DateTime dateTime)
{
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
var userDateTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
return DateTime.SpecifyKind(userDateTime, DateTimeKind.Local);
}
However, the following test fails at the last line; the converted DateTime
does not know that it should be in daylight savings time.
[Test]
public void UtcToUserTimeZoneShouldWork()
{
var utcDateTime = new DateTime(2014, 6, 1, 12, 0, 0, DateTimeKind.Utc);
Assert.IsFalse(utcDateTime.IsDaylightSavingTime());
var dateTime = Utils.UtcToUserTimeZone(utcDateTime);
Assert.IsTrue(dateTime.IsDaylightSavingTime());
}
Note that this only fails when my Windows time zone is set to (UTC) Co-ordinated Universal Time. When it is set to (UTC) Dublin, Edinburgh, Lisbon, London (or any other northern-hemisphere time zone that observes daylight savings), the test passes. If you change this setting in Windows a restart of Visual Studio is required in order for the change to fully take effect.
What am I missing?
Your last line specifies that the value is in the local time zone of the system it's running in - but it's not really... it's converted using a different time zone.
Basically DateTime
is somewhat broken, in my view - which makes it hard to use correctly. There's no way of saying "This DateTime
value is in time zone x" - you can perform a conversion to find a specific local time, but that doesn't remember the time zone.
For example, from the docs of DateTime.IsDaylightSavingTime
(emphasis mine):
This method determines whether the current DateTime value falls within the daylight saving time range of the local time zone, which is returned by the TimeZoneInfo.Local property.
Obviously I'm biased, but I'd recommend using my Noda Time project for this instead - quite possibly using a ZonedDateTime
. You can call GetZoneInterval
to obtain the ZoneInterval
for that ZonedDateTime
, and then use ZoneInterval.Savings
to check whether the current offset contains a daylight savings component:
bool daylight = zonedDateTime.GetZoneInterval().Savings != Offset.Zero;
This is slightly long-winded... I've added a feature request to consider adding an IsDaylightSavingTime()
method to ZonedDateTime
as well...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With