TimeZoneInfo.ConvertTimeToUtc issue

It depends on how the myRecord.StartTime was originated.

  • If you got it from DateTime.Now, then it will have a Local kind.
  • If you got it from DateTime.UtcNow then it will have an Utc kind.
  • If you got it from new DateTime(2013,5,1) then it will have an Unspecified kind.

It also depends on where you got myTimeZone from. For example:

  • TimeZoneInfo.Local
  • TimeZoneInfo.Utc
  • TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

The TimeZoneInfo.ConvertTimeToUtc function will only operate if it can match the zone to the kind you give it. If both are local, or both are UTC, then it will work. If you are giving it a specific zone, then the kind should be unspecified. This behavior is documented on MSDN.

You can easily reproduce the exception consistently:

var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);

Assuming you don’t live in Fiji, this will error every time. You basically said, “convert my local time, in some other zone, to utc” – which doesn’t make sense.

It probably works in your dev environment because the value you’re testing for myTimeZone happens to be the local zone for the developer.

Regarding your change – sure you can force the kind to be unspecified, and that changes the meaning of what you are doing such that it makes sense. But are you sure this is what you want? What is the .Kind of the date before hand? If it’s not already Unspecified, then it is carrying some intent. You should probably go back to the source of this data and make sure it is what you expect.

If all of this sounds crazy, mad, frustrating, and bizarre, it’s because the DateTime object stinks. Here’s some additional reading:

  • What’s wrong with DateTime anyway?
  • The case against DateTime.Now

You might consider using NodaTime instead. Its API will prevent you from making these types of common mistakes.

Leave a Comment