【问题标题】:How to present date (without time element) to users from different timezones?如何向不同时区的用户显示日期(没有时间元素)?
【发布时间】:2013-08-20 14:08:56
【问题描述】:

我想知道如何向不同时区的用户显示日期(没有时间元素)。假设日期存储在某个服务器上的某个数据库中,该服务器在某个时区(例如 UTC+6)运行,并且应用程序服务器运行在同一台机器上(或至少在同一时区)。应用程序必须处理两种类型的时间值:A/ DateTime(例如 2013-08-20 08:00 UTC)和 B/Date(例如 2013- 08-20)。

A/ DateTime 很容易处理,因为它代表了历史中的某个特定点。例如登月。它存储在数据库中的 UTC 中,每当它呈现给客户时,它就会转移到他的时区,以便适合他的现实。所以 2013-08-20 08:00 UTC = 2013-08-20 14:00 UTC+6 = 2013-08-19 22:00 UTC-10。每个客户都在看同一个时间点 = 从他的角度来看同一个事件,一切都很美好。

B/日期 = 问题。这种类型的时间值代表历史中的特定日期。由于它没有时间元素,它不能转移到不同的时区。将带有零时间分量的日期存储为 2013-08-20 00:00 UTC 并在没有时间分量的情况下向用户呈现它似乎很容易。但是在将其从 UTC-x 时区转移到 2013-08-19 之后,这是错误的,因为我们真的不知道历史上的这一点在世界的哪个地方被认为是昨天以及今天仍然在哪里。实际上,地球上的某些时间点存在三个不同的日期 (http://en.wikipedia.org/wiki/International_Date_Line)。

问题的一个很好的例子是发票的到期日。当您在 UTC+6 时区开具到期日为 2013 年 8 月 20 日的发票并将其存储在位于 UTC 的服务器上时,中国应该何时付款?在基于 UTC 的服务器上是 2013-08-19 还是仍然是 2013-08-20?

提出问题:

应该如何存储和处理没有时间元素的日期,以便可以从多个时区(包括超过 12 小时的差异)为客户提供服务?应该转移吗?它应该保持相同的日期吗?您如何在项目中处理这种情况?

非常感谢您阅读到此为止。任何参考或想法表示赞赏。我能找到的唯一相关材料是前面提到的 wiki 文章,但老实说,我不确定我的问题是否有答案。大多数文章都与日期时间偏移有关,但目前这部分处理得很好。

附:应用程序服务器是用 Java 编写的,所以我将这个 Java 相关问题标记为鼓励 Java 特定解决方案(如果有的话)。

【问题讨论】:

  • 我们当然可以为您提供解决此问题的最佳方法的建议,但我认为必须决定在这种发票情况下您希望发生什么。我们无法告诉您用户查看不同日期是否合适。一旦您了解了需求,我们就可以就如何实施解决方案提出建议。我猜在许多情况下,最好的办法是避免使用仅限日期的字段。即使在开票的情况下,也应在开具发票的国家/地区的到期日次日凌晨 12 点之前支付发票。

标签: java database date datetime timezone


【解决方案1】:

首先,我很高兴看到您对此有所考虑!许多开发人员忽略了这些细节,根据您的应用程序要求,这些细节可能非常重要。

在 Java 中,您应该使用 Joda Time 库来解决这些问题。它将帮助您区分您正在谈论的概念。

  • 您确定的第一个概念在 Joda Time 中称为Instant。当绑定到一个时区时,它被称为DateTime

  • Joda Time 中的第二个概念称为LocalDate

  • 您还确定了 DateMidnight 类型 - 我同意它可能无法满足您的特定需求。

重要的是要意识到LocalDate 并不真正位于任何时区。这不是瞬时时间线上的片刻。这只是日历上的一个位置。它映射到一个真实的时间点将取决于你如何解释它。

正如邓肯在 cmets 中指出的那样 - 很难直接建议您应该做什么,因为不同的企业在这方面有不同的要求。但这里有一些不同的方法:

  • 您可以将LocalDate 绑定到您客户所在时区的一天结束时,这意味着您公司的每位客户都有不同的时刻。

  • 您可以将LocalDate 绑定到您公司所在时区的一天结束时,这意味着每个客户的不同时刻。

  • 您的公司政策可以规定工作日由 UTC 定义。

您应该仔细考虑每个选项的实际含义。例如,由于您正在讨论发票到期日,您可能希望允许一个宽限期。

最后一点 - 您应该始终确保您的代码不关心服务器的时区是什么。您可以轻松地部署到具有特定时区的服务器,并且您不希望它破坏任何东西。巧妙地使用 UTC 或 Date/Time/Offset 类型将在特定时刻解决这个问题。但是由于LocalDate 不是一个确切的时间点 - 您必须小心从应用程序逻辑中的某个 时区获取它。不要只向服务器询问“现在”并假设这是正确的区域。

【讨论】:

    猜你喜欢
    • 2012-07-22
    • 2019-08-24
    • 2011-07-13
    • 2018-09-07
    • 1970-01-01
    • 2018-01-14
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多