Parsing UTC Time

It all started with simple requirement: there is UTC time string (e.g. 21:00) and you should parse it into UTC DateTime. Simplest code ever:

var time = DateTime.ParseExact(text, "HH:mm",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.NoCurrentDateDefault);

Only issue is that it does not work. While it looks good on first look, more careful investigation shows that its type is not Utc but Unspecified. While this might not seem as a major pain, it does make a difference.

Let’s assume that you send proper UTC time to some function that does time.ToUniversalTime(). Function will just return exactly same time back. If you do same with Unspecified time, function will adjust it for time zone and you will get back completely different time than what you started with.

Well, fixing this is easy, just add AssumeUniversal flag:

var time = DateTime.ParseExact(text, "HH:mm",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.NoCurrentDateDefault
                             | DateTimeStyles.AssumeUniversal);

Unfortunately it does not work. While description says “If no time zone is specified in the parsed string, the string is assumed to denote a UTC”, flag actually causes our time to be Local. Weird.

To properly parse time you need one more flag:

var time = DateTime.ParseExact(text, "HH:mm",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.NoCurrentDateDefault
                             | DateTimeStyles.AssumeUniversal
                             | DateTimeStyles.AdjustToUniversal);

This will finally cause our time to be of Utc kind.

Code sample is available.