如何向来自不同时区的用户呈现日期(不包含时间元素)?

3
我想知道如何向来自不同时区的用户呈现一个日期(不包含时间)。假设日期存储在某个数据库中,该数据库运行在某个时区(例如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/Date = THE PROBLEM。这种类型的临时值代表历史上的特定一天。由于它没有时间元素,因此无法转换到不同的时区。将日期与归零的时间组件一起存储似乎很容易,例如2013-08-20 00:00 UTC,并将其呈现给用户时去掉时间组件。但是,在转换后,这将导致UTC-x时区的2013-08-19,这是错误的,因为我们不知道这个历史点在世界上哪个地方被认为是昨天,哪个地方仍然是今天。实际上,在某些情况下,地球上有三个不同的日期(http://en.wikipedia.org/wiki/International_Date_Line)。
问题的很好的例子是发票的到期日期。当您在UTC +6时区发出到期日期为2013-08-20的发票并将其存储在基于UTC的服务器上时,中国的某个人应该何时支付?它是基于UTC的服务器上的2013-08-19还是仍然是2013-08-20?
提出问题:
没有时间元素的日期应如何存储和处理,以便能够向来自多个时区(包括超过12小时的差异)的客户提供服务?它应该移动吗?应该保持相同的日期吗?您如何在项目中处理这种情况?
非常感谢您阅读到这里。欢迎任何参考或想法。我唯一能接触到的相关材料是之前提到的维基文章,但老实说,我不确定我的问题是否有答案。大多数文章都与日期时间转换相关,但该部分已经处理得很好了。
附:应用程序服务器是使用Java编写的,因此我将此问题标记为与Java相关,以鼓励提供Java特定的解决方案(如果有)。

我们当然可以就解决这个问题给您提供建议,但我认为必须决定在这种发票情况下您想要发生什么。我们无法告诉您用户是否应该看到不同的日期。一旦您了解了需求,我们只能就如何实现解决方案提供建议。我猜在许多情况下,最好的想法是避免仅限日期的字段。即使在发票的情况下 - 发票应该在到期日后的第二天12点之前支付,这是发出发票的国家的规定。 - Duncan Jones
1个回答

2
首先,我很高兴看到您已经考虑了这些问题!许多开发人员会忽略这些细节,但根据您的应用要求,这可能非常重要。
在Java中,您应该使用Joda Time库来处理这些问题。它将帮助您区分您所讨论的概念。
您所提到的第一个概念在Joda Time中被称为Instant。当与时区相关联时,它被称为DateTime
Joda Time中的第二个概念是LocalDate
您还提到了DateMidnight类型 - 我同意它可能不适用于您特定的需求。
需要注意的是,LocalDate实际上并没有任何时区。它不是瞬时时间线上的一个时刻。它只是日历上的一个位置。它映射到实际时间点将取决于您如何解释它。
正如 Duncan 在评论中指出的那样,很难直接建议您应该怎么做,因为不同的企业在这方面有不同的要求。但是以下是一些不同的方法:
  • 您可以将 LocalDate 绑定到客户所在时区的当天结束时间,这意味着对于公司每个客户来说,时间点都不同。

  • 您可以将 LocalDate 绑定到公司所在时区的当天结束时间,这意味着对于每个客户来说,时间点都不同。

  • 您可以制定一个公司政策,定义工作日以 UTC 为准。

您应该仔细考虑每种选项的实际影响。例如,由于您正在谈论到期日期发票,您可能希望允许宽限期。
最后一点 - 您应该始终确保您的代码不关心服务器的时区。您可以轻松地部署到具有特定时区的服务器,并且不希望它破坏任何东西。在特定时刻,智能使用UTC或日期/时间/偏移类型将解决此问题。但由于LocalDate并不是一个精确的时间点 - 您必须小心地从应用程序逻辑中获取它来自某个时区。不要仅仅向服务器请求“现在”,并假设那是正确的时区。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接