我正在创建一个基于浏览器的单页应用程序,该应用程序将从我控制的API中以JSON形式检索信息。API通常会返回大型、复杂的对象图(对象中的对象等)。许多对象都包含"日期字段"(即仅与日期相关的字段)-也就是说,如果将字段设置为"2015年4月1日",则无论用户的时区、夏令时等如何,用户都应始终将其显示为4月1号。当然,API服务器的时区不应对显示的日期产生影响(并且可以假定为永久固定)。
在服务器端API代码中,我可以很容易地识别这些"日期字段",并可以完全灵活地在将它们发送到客户端之前以任何方式对其进行预处理。
在客户端上,这些日期将以多种方式使用(显示在文本框和标签中,传递到AngularJS"日期"过滤器,传递到第三方日期选择器控件,等等)。据我所知,这里的最低公分母是Date()构造函数——如果浏览器的JavaScript Date()构造器能够正确解释日期,那么其他一切都会正常工作。
因此,我的第一个想法是预处理这些仅限日期的字段,使它们成为date()构造函数能够正确解释的格式。事实证明,找到这样的格式并非易事(请参阅我的相关问题:JavaScript日期格式保证在现代浏览器中被解释为本地时间)
我的另一个想法是在客户端对API响应进行后处理(本质上,使用例如moment.js手动解析从API返回的所有字符串日期),但我希望避免梳理巨大的对象图并查找所有日期对客户端性能的影响。
我猜这不是一个新的或特别独特的问题。还有其他我忽略的解决方案吗?如何在保持日期时区不可知的情况下,将服务器上的仅日期字段与浏览器客户端通信?
在JSON中,最好的建议是坚持ISO8601标准。对于没有时间的日期,这将是YYYY-MM-DD
,例如:
{
"fooDate" : "2015-12-15"
}
造成这种情况的原因有很多,但通常情况下,您应该以符合标准的格式通过导线发送数据,以便目的明确。某些解析器(无论是JavaScript、浏览器还是其他)可能会错误地解释它,这在该环境中是需要调整的,而不是在序列化中。
因此,如果你在浏览器中收到了这个消息,你可以用斜杠替换连字符(根据我对另一个问题的回答,也可以在这里显示),或者用moment.js这样的库进行解析,或者用连字符分割字符串,并从部分中构建日期(如果你要发送到Date
构造函数,请小心从月份中减去1)。
需要考虑的另一点是,您的后端平台默认情况下可能不会使用仅限日期的表单。例如,如果在.NET中使用DateTime
来存储仅限日期的值,则该值将被视为午夜的日期。因此,序列化最终可能会包含时间,而这在您的场景中是不希望的。对于.NET开发人员,请使用NodaTime的LocalDate
,或等待CoreFXLab的System.Date
进入生产就绪状态。
其他平台可能也有类似的问题,但关键是,如果时间对你的数据没有意义,那么就不应该发送。不要发送"2015-12-15T00:00:00"
,而实际上是指"2015-12-15"
。它们是两个不同的概念。
我们有一个类似的应用程序,其中有一个叫做"检查日期"的东西,它应该是一个没有时间的日期。我们的应用程序运行在多个国家和时区,我们希望向所有用户显示相同的日期。
当使用不带时间的日期时,大多数浏览器和服务器系统都会假定时间为00:00:00。在服务器上,我们的应用程序以UTC存储所有时间,用户总是在浏览器中看到本地时间。
我们遇到的问题是,一些用户会将之前的日期视为检查日期,因为他们在西半球。
想想看,一个简单的日期,比如说2015年12月18日,实际上并不是完整的信息,除非你也说明了该日期的位置。目前在日本排名第18,但在美国排名第17。
然后我们意识到,我们可以通过将日期转换为字符串(就在服务器上)并向用户显示来忽略时区。但是,当我告诉美国用户18日(在日本)进行了一次检查,这对他来说意味着什么?就他而言,检查发生在17日。
字符串解决方案对我们不起作用。我们选择了下一个最佳选项:根据执行日期的时区,为日期指定下午12:00的时间。这给了我们最好的近似值,每个人都很高兴。靠近检查时区的用户看到了正确的日期,而对面的用户也看到了正确日期(根据他们的说法)。:)