Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中的DST实现在发送到MVC控制器时导致问题_Javascript_Ajax_Asp.net Mvc_Json_Datetime - Fatal编程技术网

JavaScript中的DST实现在发送到MVC控制器时导致问题

JavaScript中的DST实现在发送到MVC控制器时导致问题,javascript,ajax,asp.net-mvc,json,datetime,Javascript,Ajax,Asp.net Mvc,Json,Datetime,我的客户是保险行业的,他要求提供潜在被保险人的出生日期。它使用jQuery日期选择器输入web表单,使用Knockout连接到模型属性,并通过JSON中的ajax发送到MVC4控制器 一些投保人收到的保险文件中有错误的出生日期。在随后的调查中,我们发现,除了数据输入错误(这些错误非常微小)外,错误日期还集中在以下两个时期: 3月最后三周至4月初 十月的最后一周到十一月的第一周 由于我们的客户在美国/蒙特利尔时区,我立即想到了DST的问题 通过阅读几篇文章和其他堆栈溢出问题,我了解到ECMAS

我的客户是保险行业的,他要求提供潜在被保险人的出生日期。它使用jQuery日期选择器输入web表单,使用Knockout连接到模型属性,并通过JSON中的ajax发送到MVC4控制器

一些投保人收到的保险文件中有错误的出生日期。在随后的调查中,我们发现,除了数据输入错误(这些错误非常微小)外,错误日期还集中在以下两个时期:

  • 3月最后三周至4月初
  • 十月的最后一周到十一月的第一周
由于我们的客户在美国/蒙特利尔时区,我立即想到了DST的问题

通过阅读几篇文章和其他堆栈溢出问题,我了解到ECMAScript 5标准规定实现必须考虑当前的DST规则,并且不需要考虑DST的更改历史。目前唯一不符合此规范的浏览器是IE10(稍后将详细介绍)

根据此规范,浏览器将报告如下日期(在Chrome中测试):

尽管.NET平台报告的日期正确,但如下所示:

DateTime dt = new DateTime(2006, 10, 31, 0, 0, 0);
Console.WriteLine("{0:MM/dd/yy H:mm:ss zzz}", dt);
// 10-31-06 0:00:00 -05:00
dt = new DateTime(2008, 10, 31, 0, 0, 0);
Console.WriteLine("{0:MM/dd/yy H:mm:ss zzz}", dt);
// 10-31-08 0:00:00 -04:00
此问题的一个原因是,如果被保险人在2007年10月的最后一周出生,UTC时间将错误地报告给我的MVC控制器,例如:

Javascript日期对象:

new DateTime(2006, 9, 31, 0, 0, 0);
10-30-06 23:00:00 GMT
(new Date(2006, 9, 31, 0, 0, 0)).getTime()
// 1162267200000
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1162267200000);
Console.WriteLine("{0}", dt);
// 2006-10-31 04:00:00
.Net解析JSON数据并获取:

new DateTime(2006, 9, 31, 0, 0, 0);
10-30-06 23:00:00 GMT
(new Date(2006, 9, 31, 0, 0, 0)).getTime()
// 1162267200000
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1162267200000);
Console.WriteLine("{0}", dt);
// 2006-10-31 04:00:00
在测试期间,我发现JavaScript中日期对象的内部表示与.Net DateTime的内部表示不兼容,并且我无法使用JavaScript表示滚动我自己的解析器:

Javascript:

new DateTime(2006, 9, 31, 0, 0, 0);
10-30-06 23:00:00 GMT
(new Date(2006, 9, 31, 0, 0, 0)).getTime()
// 1162267200000
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1162267200000);
Console.WriteLine("{0}", dt);
// 2006-10-31 04:00:00
.Net:

new DateTime(2006, 9, 31, 0, 0, 0);
10-30-06 23:00:00 GMT
(new Date(2006, 9, 31, 0, 0, 0)).getTime()
// 1162267200000
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1162267200000);
Console.WriteLine("{0}", dt);
// 2006-10-31 04:00:00
(这是错误的,因为它表示为当地时间2006年10月30日23:00。)

对于我的客户机的用例,因为我感兴趣的是日期部分,所以我可以将日期对象的时间部分设置为中午,这将使我免受JavaScript方面所有日期错误解释的影响。不幸的是,这是一个丑陋的补丁,它无法解决其他潜在的情况,例如,如果我的客户希望我们实现一个功能,要求我们提供过去发生的事件的准确日期和时间

另一种方法是编写一种算法来检测控制器中可能存在问题的DST周,并在有问题的周内获得日期时设置正确的时间。不幸的是,考虑到ECMAScript 6标准规定必须遵守DST更改历史(因此未来所有浏览器都应该正确处理这种情况),并且考虑到IE10已经正常工作,我担心将来会出现问题。从架构上讲,这种方法似乎也是错误的

另一个要考虑的方面是,如果我必须将模型从客户机传递到服务器,然后再返回到客户机,我将需要有一种方法来重新创建“坏”JavaScript日期对象,以确保不影响应用程序客户端的显示。 似乎没有一个解决方案是正确的和可扩展的。我不敢相信以前从来没有人处理过这个问题

我怎样才能永久性地解决这个问题,并以一种可以应用于所有其他JavaScript/MVC项目的方式解决这个问题

编辑#1-与问题没有直接关系的其他信息:

new DateTime(2006, 9, 31, 0, 0, 0);
10-30-06 23:00:00 GMT
(new Date(2006, 9, 31, 0, 0, 0)).getTime()
// 1162267200000
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(1162267200000);
Console.WriteLine("{0}", dt);
// 2006-10-31 04:00:00
正如@matt johnson所指出的,很少有使用时区信息的情况。然而,在这种情况下,投保人的出生日期与我的客户所在的时区有关。让我们举一个17岁的孩子为例,他住在不列颠哥伦比亚省维多利亚州,生日是12月2日。如果他在12月1日22:00提交保险报价,即使他仍然17岁,保险报价也会被接受,因为他已经在我客户的时区18岁了。同样的规则也适用于保险定价。这是法律要求

我只是想说清楚,我正在寻找一个全面的解决方案,它可以应用于任何其他项目。具体的问题是:在2007年之前的几年中,Javascript只在特定的几周内报告时间,并有1小时的偏移量。无论我如何表示时间(本地时区或UTC),此偏移量始终存在,因为错误的是底层数据(而不是数据表示)


我使用了“将时间部分设置为中午”的变通方法来规避该错误,但潜在的问题仍然存在。如果我的客户要求我们开发一个web应用程序,要求我们获取过去某个特定事件的日期和时间,会发生什么情况?例如:“请说明事故发生的确切日期和时间:2005年10月31日19:32”。MVC控制器将时间设置为18:32。

您忽略了.Net的部分
日期时间结构。具体来说,您没有考虑任何
DateTime
.Kind
属性是三个可能的
DateTimeKind
值之一

如果使用UTC值,则需要设置
DateTimeKind.UTC
。由于JavaScript的数值是基于UTC的,因此您应该使用此值进行转换:

DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
                      .AddMilliseconds(1162267200000);
另外,您正在做一些有点奇怪的事情,在具有
DateTimeKind.Unspecified
DateTime
上使用
zzz
格式化程序。在这种情况下,实际上没有任何时区与该值关联,但是.Net会假定您希望它的行为就像是
DateTimeKind.Local
,因为
zzz
格式化程序在其他情况下没有意义

您确实需要小心不要使用
DateTimeKind.Local
值(例如
DateTime.Now
)或任何未指定类型可能被误解为Local的值(例如