TimeZoneInfo.ConvertTimeToUtc issue

C#.NetDatetime

C# Problem Overview


We had an issue where one developer creates the below code and it works on his DEV environment. But when it's checked into QA, the code breaks with the below error message:

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);

> The conversion could not be completed because the supplied DateTime > did not have the Kind property set correctly. For example, when the > Kind property is DateTimeKind.Local, the source time zone must be > TimeZoneInfo.Local.

On my DEV environment, the above code generates the same error as the QA server. I applied the below change to fix the problem:

DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);

Why does the first code example work on DEV1's environment but break on my DEV environment and on our QA server?

C# Solutions


Solution 1 - C#

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:

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

Solution 2 - C#

in this example i have converted the local timezone to unspecified type so it is working fine for me by using "DateTime.SpecifyKind()" method

> DateTime.SpecifyKind(utc,DateTimeKind.Unspecified);

this method Creates a new DateTime object that has the same number of ticks as the specified DateTime, but is designated as unspecified type of DateTimeKind.

> public static DateTime ConvertLocalDate(DateTime utc) > { > > string id = ConfigurationManager.AppSettings["Timezone"].ToString(); > TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(id); > utc = DateTime.SpecifyKind(utc,DateTimeKind.Unspecified); > DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(utc, cstZone); > return cstTime; > }

Solution 3 - C#

I found a really simple solution here https://kiranpatils.wordpress.com/2011/01/09/the-conversion-could-not-be-completed-because-the-supplied-datetime-did-not-have-the-kind-property-set-correctly-for-example-when-the-kind-property-is-datetimekind-local-the-source-time-zone-must/

Which appears only to be happening when you use DateTime.Now. I update my code like following and it is working again :)

DateTime currentTime = new DateTime(DateTime.Now.Ticks, DateTimeKind.Unspecified);

Solution 4 - C#

Basically what was said in previous answers, but to trim it down:

DateTime.Now or DateTime.Today sets the Kind to Local, so change this to Unspecified

In the method that handles the dates:

// Incoming date has DateTimeKind.Local 
 var localDateTime = DateTime.Now;

// Set to unspecified
 var unspecifiedDateTime = DateTime.SpecifyKind(localDateTime, DateTimeKind.Unspecified); 

I was only receiving this when deployed, then realised a library was passing DateTime.Now rather than new DateTime(...) to a method.

Solution 5 - C#

The accepted answer does a great job explaining the cause. But I'm still adding my 2 cents for completeness:

When serializing DateTime objects, some serializers will mess up the Kind of your DateTime properties. We've had this problem when caching POCO objects in Redis using ProtoBuf and MessagePack serializers.

So, if you know that's the case, then it's perfectly fine to force the kind of your datetime variable to "Unspecified" like this:

myDateTime = DateTime.SpecifyKind(myDateTime, DateTimeKind.Unspecified);

Solution 6 - C#

in C#


public static DateTime IndianDateTime(DateTime currentTime)
{
DateTime cstTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time");
return cstTime;
}

In VB


Public Shared Function IndianDateTime(ByVal currentTime As DateTime) As DateTime
Dim cstTime As DateTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time")
Return cstTime
End Function

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJerryView Question on Stackoverflow
Solution 1 - C#Matt Johnson-PintView Answer on Stackoverflow
Solution 2 - C#Pradeep Kumar DasView Answer on Stackoverflow
Solution 3 - C#Atta H.View Answer on Stackoverflow
Solution 4 - C#DanView Answer on Stackoverflow
Solution 5 - C#Alex from JitbitView Answer on Stackoverflow
Solution 6 - C#iApps Creator IndiaView Answer on Stackoverflow