Используя JSON.Net, из следующих 5 тестов, первый и последний проход, в то время как остальные терпят неудачу:
[Test, Sequential]
public void WhyCantIDeserializeThisDateWhen2011Works(
[Values(1980, 1980, 1980, 1980, 1980, 1980, 1980)] Int32 year,
[Values(10, 10, 10, 10, 11, 11, 11)] Int32 month,
[Values(26, 27, 30, 31, 1, 2, 3)] Int32 day)
{
var obj = new {
Title = "Will this be able to serialize the DateTime field?",
Timestamp = new DateTime(year, month, day)
};
var type = obj.GetType();
var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
dynamic deserialized = Newtonsoft.Json.JsonConvert.DeserializeObject(serialized, type);
Assert.AreEqual(obj.Title, deserialized.Title);
Assert.AreEqual(obj.Timestamp, deserialized.Timestamp);
}
Вот некоторые из выводов:
[snip]
Test 'Rds.Infrastructure.Serializers.Tests.JsonSerializerTests.WhyCantIDeserializeThisDateWhen2011Works(1980,11,2)' failed:
Expected: 1980-11-02 00:00:00.000
But was: 1980-11-01 23:00:00.000
at CallSite.Target(Closure , CallSite , Type , DateTime , Object )
UnitTests\Rds.Infrastructure\Serializers\JsonSerializerTests.cs(141,0): at Rds.Infrastructure.Serializers.Tests.JsonSerializerTests.WhyCantIDeserializeThisDateWhen2011Works(Int32 year, Int32 month, Int32 day)
2 passed, 5 failed, 0 skipped, took 627.55 seconds (NUnit 2.5.5).
Ошибка типична для всех ошибок - когда она перезагружает дату, а не является указанным днем, она появляется как предыдущий день в 23:00. Это особенно странно, если я изменю год на 2011 год, все эти тесты пройдут.
Я копался в коде JSON.Net - метод ParseDate класса JsonTextReader считывает значение. Используя 27 октября 2011 года в качестве примера, мои комментарии:
private void ParseDate(string text)
{
string value = text.Substring(6, text.Length - 8);
DateTimeKind kind = DateTimeKind.Utc;
int index = value.IndexOf('+', 1);
if (index == -1)
index = value.IndexOf('-', 1);
TimeSpan offset = TimeSpan.Zero;
if (index != -1)
{
kind = DateTimeKind.Local;
offset = ReadOffset(value.Substring(index));
value = value.Substring(0, index);
}
long javaScriptTicks = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
// The date time gets loaded here, as Oct 27 2011 3am
DateTime utcDateTime = JsonConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
#if !NET20
if (_readType == ReadType.ReadAsDateTimeOffset)
{
SetToken(JsonToken.Date, new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset));
}
else
#endif
{
DateTime dateTime;
switch (kind)
{
case DateTimeKind.Unspecified:
dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
break;
case DateTimeKind.Local:
// Here, it gets converted to local time, Oct 26 2011 at 11pm!
dateTime = utcDateTime.ToLocalTime();
break;
default:
dateTime = utcDateTime;
break;
}
SetToken(JsonToken.Date, dateTime);
}
}
Как отмечалось выше, ошибка возникает только для дат с 27 октября 1980 года по 2 ноября 1980 года. Я не проводил тесты, чтобы определить, какие годы являются проблемами, но тесты проходят, если вы используете 2011.
Полагаю, это связано с изменениями в летнем времени?
Кто-нибудь имеет представление о том, что здесь происходит?