【发布时间】:2011-11-10 20:42:01
【问题描述】:
使用 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).
该错误是所有错误的典型错误 - 当它重新加载日期而不是指定日期时,它会在前一天晚上 11 点出现。这特别奇怪,因为如果我将年份更改为 2011 年,所有这些测试都会通过。
我已经深入研究了 JSON.Net 代码 - JsonTextReader 类的 ParseDate 方法读取值。以 2011 年 10 月 27 日为例,cmets 是我的:
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);
}
}
如上所述,该错误仅发生在 1980 年 10 月 27 日至 1980 年 11 月 2 日期间。我尚未运行测试以确定哪些年份存在问题,但如果您使用 2011 年,测试确实通过了。
我猜这与夏令时的变化有关?
有人知道这里发生了什么吗?
【问题讨论】:
-
发生在 1981 年吗? 1985 年?你在哪个时区?
-
我在大西洋时区。我回去尝试了不同的年份,在我尝试的其他年份中,我得到了相同的错误结果:1981、1985、2001 和 2006。从 2007 年到 2011 年,测试都通过了。
-
想想看,2007 年美国和加拿大的夏令时延长了 - 从 3 月的第二个星期日到 11 月的第一个星期日。从 1987 年到 2006 年,它在 10 月的最后一个星期日结束。 (参考:timeanddate.com/news/time/us-daylight-saving-extended.html)这可能是与此相关的错误吗?
-
你是否有机会在 XP 上运行?
-
不。 .Net 4,Visual Studio 2010 SP1,在 Win7 虚拟机上。