I have a date serialized as a string "2012-06-20T13:19:59.1091122Z"
Using the DateTimeConverter, this gets converted to a DateTime object {22:49:59.1091122} with the Kind property set to "Local".
eg. The following test fails:
private static readonly DateTime UtcDate = new DateTime(634757951991091122, DateTimeKind.Utc);
private const string UtcSerialisedDate = "2012-06-20T13:19:59.1091122Z";
[Test]
public void DateTimeConverter_Convert_From_Utc_String()
{
// Arrange
var converter = TypeDescriptor.GetConverter(typeof(DateTime));
// Act
var result = converter.ConvertFrom(UtcSerialisedDate);
// Assert
Assert.AreEqual(UtcDate, result);
Assert.AreEqual(DateTimeKind.Utc, ((DateTime)result).Kind);
}
I'm a bit surprised by this... I would have expected that the DateTime object returned by the converter would be in UTC.
The docs do say that DateTimeConverter uses DateTime.Parse, but I'm guessing it must not use the DateTimeStyles.RoundtripKind option.
Is there any way around this?
To convert a JavaScript date object to a UTC string, you can use the toUTCString() method of the Date object. The toUTCString() method converts a date to a string, using the universal time zone. Alternatively, you could also use the Date.
Add the local time offset to the UTC time. For example, if your local time offset is -5:00, and if the UTC time is shown as 11:00, add -5 to 11. The time setting when adjusted for offset is 06:00 (6:00 A.M.).
This datetime object will have no timezone associated with it. Therefore assign the UTC timezone to this datetime object using replace(tzinfo=pytz. UTC) function. Convert the timezone of the datetime object to local timezone by calling the astimezone() function on datetime object.
var utcDate = '2011-06-29T16:52:48.000Z'; // ISO-8601 formatted date returned from server var localDate = new Date(utcDate);
The real bug here is that DateTime.Parse() without any DateTimeStyles passed should still see the "Z" and recognize that it should be parsed as UTC. But good luck getting MS to acknowledge or fix that.
The particular problem illustrated by your code sample is that the DateTimeConverter has to override methods from TypeConverter, and thus has no ability to pass extra parameters such as DateTimeStyles. It's too bad it doesn't implement some sort of static or threadstatic property for this. It does indeed take advantage of the thread's Culture.CurrentCulture, but DateTimeStyles are a separate thing from culture, so alas - that's another dead end.
I assume you are locked in to using a converter, rather than just calling parse directly? Is this a hard requirement? If not, you could do the following:
public static object ConvertFrom<T>(string value)
{
if (typeof(T) == typeof(DateTime))
return DateTime.Parse(value, null, DateTimeStyles.RoundtripKind);
var converter = TypeDescriptor.GetConverter(typeof(T));
return converter.ConvertFrom(value);
}
Another approach would be to use a DateTimeOffsetConverter
instead - it understands the Z timezone properly. You could then use the .UtcDateTime
property of the result to get back to a DateTime with a UTC kind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With