服务器或客户端在发送/接收日期时应该处理时区吗?

Posted

技术标签:

【中文标题】服务器或客户端在发送/接收日期时应该处理时区吗?【英文标题】:Should the Server or the Client handle timezone when sending/receiving dates? 【发布时间】:2014-08-30 14:06:10 【问题描述】:

我了解最佳做法是将 UTC 日期/时间存储在我们的数据库中,并以当地时区显示给用户。我们将存储时区而不是偏移量,以便支持夏令时。

哪种方式最适合处理时区?

选项 1:服务器仅使用 UTC,客户端转换为时区

html 格式发送到浏览器的所有日期均采用 UTC。客户端将使用 moment.js 或类似文件将 UTC 时间转换为正确的时区。将使用我们数据库中指定的时区而不是浏览器的本地时间,因为这可能不正确。

用户提交日期或时间时,必须先转换为UTC时间,然后再提交给服务器。

选项 2:服务器转换为时区

所有计算仍以 UTC 进行,并且在可能的最后一刻将日期/时间转换为正确的时区,例如在以 HTML 格式输出日期时。

当客户端提交任何日期/时间时,应立即转换为 UTC。

还有其他方法吗?

【问题讨论】:

您应该始终从htaccess 或从服务器php.ini 设置UTC。此外,在数据库中,日期应为UTC。这样所有的日期都是一样的。您可以使用mysqlPHP 来操作日期而无需转换。唯一的转化发生在您向用户列出日期时。 @machineaddict 我在问在客户端或服务器端转换日期是否是最佳做法。即我们是让服务器只说 UTC 还是应该处理时区转换? 根据我上面解释的方法,日期完全从服务器端处理。因此,服务器只在UTC 中交谈。 @machineaddict 如果服务器只以 UTC 进行通信,那么我们依赖 javascript 在页面加载时更改日期字符串? 如果您的用户已注册,他们可以选择他们的时区。如果用户是客人,您可以使用 javascript 更改日期以对应他们的计算机时区,显示服务器时区,或​​者您可以从他们的 ip 猜测他们的时区。一个想法是看看像vBulettinphpBB 这样的脚本如何根据用户状态(访客/登录)处理他们的时间。我的下一个项目必须是这样,所以我可能会在其中实现您的最佳答案。 【参考方案1】:

任何一个选项都有效,但每种方法都有优点和缺点。有几件事情需要考虑:

JavaScript 的原生时区转换仅限于运行它的机器的本地时区,也是seriously broken。如果您打算在客户端中转换值,则需要one of the time zone libraries listed here。我个人推荐moment-timezone。

在客户端(使用任何库)中转换值将需要时区数据,如果您想支持世界上所有的时区,这可能会有点大。您可能需要考虑将数据限制为满足您要求的最小子集。

服务器端时区转换也需要有效的时区数据。 PHP 已内置此功能,您可以随时了解the timezonedb package in PECL 的更新。

您还使用 ASP.Net 标记了您的问题。 .Net 包括TimeZoneInfo,它仅提供对 Microsoft 时区的支持。如果您想要标准 IANA 时区(如 PHP 中使用的时区),那么您将需要一个库。我推荐Noda Time。您可以在the timezone tag wiki 中阅读有关不同类型时区的更多信息。

如何交付最终结果取决于您编写的应用程序类型。

如果您正在创建一个“传统”网页,其中 HTML 在服务器端呈现,那么您将呈现人类可读的字符串。这意味着不仅要了解时区,还要了解用户的语言环境,这样您就可以使用适合文化的格式。

这与时区完全无关。例如,您可能是美国人,使用 MM/DD/YYYY 格式,但实际上仍位于欧洲并使用欧洲时区。

如果您的服务器通过 API(即 JSON、XML 等)提供结果,那么您的结果应该是机器可读的。最好使用ISO 8601 格式。具体来说,时间戳应按照RFC 3339 中的说明传递。

这意味着它们应该始终包含Z(对于 UTC 值)或偏移量(对于本地值)。因此,您可能会考虑用户的时区,但您提供的结果应该包括本地偏移量,因此它是明确的。

例如,您有 UTC 值 2014-07-09T12:00:00Z,然后在 America/Los_Angeles 中它是 2014-07-09T05:00:00-07:00,这就是应该通过 API 传递的内容。

在客户端,您可以使用 moment.js 之类的库为用户呈现该值。例如:

     var s = moment.parseZone("2014-07-09T05:00:00-07:00").format("LLL");

相关:How to properly work with Timezone?

【讨论】:

以上是关于服务器或客户端在发送/接收日期时应该处理时区吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用mongodb在utc中存储日期时如何处理时区问题?

REST API 的验收测试 - 我应该处理所有情况吗?

如何处理服务器和客户端之间的时区?

如何处理服务器和本机android应用程序之间的时区差异?

使用用户本地日期时间保存日期时间问题

反序列化 JSON 日期无时区