Why can't DateTime.Parse parse UTC date
C#DatetimeParsingC# Problem Overview
Why can't it parse this:
DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC")
C# Solutions
Solution 1 - C#
It can't parse that string because "UTC" is not a valid time zone designator.
UTC time is denoted by adding a 'Z' to the end of the time string, so your parsing code should look like this:
DateTime.Parse("Tue, 1 Jan 2008 00:00:00Z");
From the Wikipedia article on ISO 8601
> If the time is in UTC, add a 'Z' > directly after the time without a > space. 'Z' is the zone designator for > the zero UTC offset. "09:30 UTC" is > therefore represented as "09:30Z" or > "0930Z". "14:45:15 UTC" would be > "14:45:15Z" or "144515Z". > > UTC time is also known as 'Zulu' time, > since 'Zulu' is the NATO phonetic > alphabet word for 'Z'.
Solution 2 - C#
Assuming you use the format "o" for your datetime so you have "2016-07-24T18:47:36Z", there is a very simple way to handle this.
Call DateTime.Parse("2016-07-24T18:47:36Z").ToUniversalTime()
.
What happens when you call DateTime.Parse("2016-07-24T18:47:36Z")
is you get a DateTime
set to the local timezone. So it converts it to the local time.
The ToUniversalTime()
changes it to a UTC DateTime
and converts it back to UTC time.
Solution 3 - C#
Just use that:
var myDateUtc = DateTime.SpecifyKind(DateTime.Parse("Tue, 1 Jan 2008 00:00:00"), DateTimeKind.Utc);
if (myDateUtc.Kind == DateTimeKind.Utc)
{
Console.WriteLine("Yes. I am UTC!");
}
You can test this code using the online c# compiler:
I hope it helps.
Solution 4 - C#
You need to specify the format:
DateTime date = DateTime.ParseExact(
"Tue, 1 Jan 2008 00:00:00 UTC",
"ddd, d MMM yyyy HH:mm:ss UTC",
CultureInfo.InvariantCulture);
Solution 5 - C#
or use the AdjustToUniversal DateTimeStyle in a call to
DateTime.ParseExact(String, String[], IFormatProvider, DateTimeStyles)
Solution 6 - C#
To correctly parse the string given in the question without changing it, use the following:
using System.Globalization;
string dateString = "Tue, 1 Jan 2008 00:00:00 UTC";
DateTime parsedDate = DateTime.ParseExact(dateString, "ddd, d MMM yyyy hh:mm:ss UTC", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal);
This implementation uses a string to specify the exact format of the date string that is being parsed. The DateTimeStyles parameter is used to specify that the given string is a coordinated universal time string.
Solution 7 - C#
It's not a valid format, however "Tue, 1 Jan 2008 00:00:00 GMT" is.
The documentation says like this:
A string that includes time zone information and conforms to ISO 8601. For example, the first of the following two strings designates the Coordinated Universal Time (UTC); the second designates the time in a time zone seven hours earlier than UTC:
2008-11-01T19:35:00.0000000Z
A string that includes the GMT designator and conforms to the RFC 1123 time format. For example:
Sat, 01 Nov 2008 19:35:00 GMT
A string that includes the date and time along with time zone offset information. For example:
03/01/2009 05:42:00 -5:00
Solution 8 - C#
Just replace "UTC" with "GMT" -- simple and doesn't break correctly formatted dates:
DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC".Replace("UTC", "GMT"))
Solution 9 - C#
I've put together a utility method which employs all tips shown here plus some more:
static private readonly string[] MostCommonDateStringFormatsFromWeb = {
"yyyy'-'MM'-'dd'T'hh:mm:ssZ", // momentjs aka universal sortable with 'T' 2008-04-10T06:30:00Z this is default format employed by moment().utc().format()
"yyyy'-'MM'-'dd'T'hh:mm:ss.fffZ", // syncfusion 2008-04-10T06:30:00.000Z retarded string format for dates that syncfusion libs churn out when invoked by ejgrid for odata filtering and so on
"O", // iso8601 2008-04-10T06:30:00.0000000
"s", // sortable 2008-04-10T06:30:00
"u" // universal sortable 2008-04-10 06:30:00Z
};
static public bool TryParseWebDateStringExactToUTC(
out DateTime date,
string input,
string[] formats = null,
DateTimeStyles? styles = null,
IFormatProvider formatProvider = null
)
{
formats = formats ?? MostCommonDateStringFormatsFromWeb;
return TryParseDateStringExactToUTC(out date, input, formats, styles, formatProvider);
}
static public bool TryParseDateStringExactToUTC(
out DateTime date,
string input,
string[] formats = null,
DateTimeStyles? styles = null,
IFormatProvider formatProvider = null
)
{
styles = styles ?? DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal; //0 utc
formatProvider = formatProvider ?? CultureInfo.InvariantCulture;
var verdict = DateTime.TryParseExact(input, result: out date, style: styles.Value, formats: formats, provider: formatProvider);
if (verdict && date.Kind == DateTimeKind.Local) //1
{
date = date.ToUniversalTime();
}
return verdict;
//0 employing adjusttouniversal is vital in order for the resulting date to be in utc when the 'Z' flag is employed at the end of the input string
// like for instance in 2008-04-10T06:30.000Z
//1 local should never happen with the default settings but it can happen when settings get overriden we want to forcibly return utc though
}
Notice the use of '-' and 'T' (single-quoted). This is done as a matter of best practice since regional settings interfere with the interpretation of chars such as '-' causing it to be interpreted as '/' or '.' or whatever your regional settings denote as date-components-separator. I have also included a second utility method which show-cases how to parse most commonly seen date-string formats fed to rest-api backends from web clients. Enjoy.
Solution 10 - C#
Not sure why, but you can wrap DateTime.ToUniversalTime in a try / catch and achieve the same result in more code.
Good luck.