Yesterday Uruguay changed their clocks, and now I keep seeing exceptions when converting specific times for their timezone:
ERROR Exception: - DateTime ConvertTimeToUtc(DateTime, String) (05/10/2014 02:31:00, America/Montevideo)
NodaTime.SkippedTimeException: Specified argument was out of the range of valid values.
Parameter name: Local time 05/10/2014 02:31:00 is invalid in time zone America/Montevideo
I understand how a local time can be invalid:
"For example, suppose the time zone goes forward at 2am, so the second after 01:59:59 becomes 03:00:00. In that case, local times such as 02:30:00 never occur."
However, what I don't understand (and I probably need more coffee), is why NodaTime is not accounting for this? Should it not be aware that 02:31 is now an invalid local time - or should I be doing additional handling to account for this?
Functions I'm calling:
var timeZone = DateTimeZoneProviders.Tzdb[timezoneName];
var localTime = LocalDateTime.FromDateTime(timeToConvert).InZoneStrictly(timeZone);;
return DateTime.SpecifyKind(localTime.ToDateTimeUtc(), DateTimeKind.Utc);
Yes, it is aware that it's an invalid local time - which is why when you specifically ask it to convert that local time into UTC, it throws an exception. It's roughly equivalent to calling Math.sqrt(-1)
.
The InZoneStrictly
call you're making specifically throws an exception on either ambiguous or skipped times. If you use InZoneLeniently
you won't get an exception, but it may not give you the result you want. Or, you could use LocalDateTime.InZone(DateTimeZone, ZoneLocalMappingResolver)
which will allow you to map invalid local date/time values however you want.
As side-notes:
localTime
variable is a ZonedDateTime
, so the name is a bit misleadingSpecifyKind
- ToDateTimeUtc
will always return a DateTime
with a kind of Utc
, hence the name.See more on this question at Stackoverflow