Java日历、日期和时间管理在多时区应用程序中的应用

15

我正在设计一个调度的网络应用程序。

我期望用户在多个不同的时区和地区添加事件。挑战在于正确呈现这些事件。

因此,举个例子:
如果一个用户处于美国东部标准时间(EST)时区,并查看由另一个用户在太平洋标准时间(PST)添加的网络研讨会事件,则要将事件的实际PST时间转换为观众的本地时间。例如,如果一项事件计划在下午2点PST,则它应该显示为下午5点EST。

我还希望注意性能问题,以防有成千上万的事件需要从实际事件时间转换为观众的本地时间。

感谢您提供任何想法和评论。
谢谢您!

1个回答

51

总的来说,安排未来事件是一个复杂的主题。您需要根据将要安排的内容进行区分:

  • 事件是否发生在一个特定的世界标准时间点?如果是这样的话,你应该记录事件时间以UTC为单位。

    例如,每24小时运行一次的任务将按照UTC时间表安排,而不是按照本地时间。它可能会从某个当地的午夜开始,但随着夏令时的变化生效,它可能会根据当地的时钟在23:00或01:00运行。

  • 然而,如果事件是由人类安排的,很可能是以本地时间为基础,所以你应该以此方式记录它。

    例如,在东部时间发生的08:00会始终发生在那个本地时间。在冬天,那将是13:00 UTC,在夏天则会是12:00 UTC。

    因此,在这种情况下,你不能以UTC为基础记录计划开始时间。这是一个非常常见的错误,因为互联网上有很多建议说"总是使用UTC存储",这在这种情况下是错误的。

    相反,你应该存储两个值 - 本地时间,如08:00和其IANA时区标识符,如America/New_York。根据事件的安排方式,你还可能需要存储重复模式或特定日期。

  • 考虑使用Joda Time而不是Java的CalendarDate类。它会为你节省很多麻烦。确保你阅读了Joda Time文档并理解它的工作原理。

    Joda Time具有在不同时区之间转换所需的所有功能 - 这是我认为你问题的主要关注点。

  • 务必制定一个程序,定期更新时区数据。随着世界各国政府对其时区的法律定义进行更改,更新将每年推出多次。你不能只部署一次然后忘记它。

  • 还要确保你了解从本地时间转换为特定UTC时刻不是一个完美的函数,因为夏令时的存在。如果事件在无效或模糊的本地时间安排,则应该在应用程序中检测和处理这个问题。你可能只是应用一些假设,或者你可能想尽办法询问用户该怎么做。

    例如,如果我每天在东部时间2:00 AM安排一个事件,那么在2013年3月10日,那个时间不存在。该事件应该发生在3:00 AM吗?还是根本不发生?

    另一个例子,如果我每天在东部时间1:00 AM安排一个事件,那么在2013年11月3日,那个时间会出现两次。该事件应该发生在第一(夏令时)实例还是第二(标准时间)实例?或者两个都发生?我应该假设其中一个,还是应该问用户他们的意思是什么?

    只有你能决定该怎么做,因为这是你的应用程序。但忽略这个问题可能会导致错误。

  • 一旦事件过去了,你可以按照需要记录它的UTC时间,或者记录它的完整本地日期时间和偏移量。两种方法都可以接受。这对


感谢你详细的回复,马特。我预计几乎所有的事件都将由人类创建。我的想法是保存时区和毫秒数,这样我就知道事件的实际本地时间,并能够将其转换为观众的时区。你是正确的,这并不像看起来那么简单... - user2754571
1
如果您存储毫秒数,例如从Date.getTime()获取的值,则该值将以UTC而非本地时间表示。如果在您的时间发生之前更改了时区规则,则可能会出现错误的值。在世界上的几个地区,这些时区更改经常发生,因此很难确定未来的本地时间是否与未来的UTC时间对齐。(我说过这很复杂。 :)) - Matt Johnson-Pint
1
дҪ еә”иҜҘдҪҝз”ЁJodaTimeзҡ„LocalDateTime(е’Ңж—¶еҢә)гҖӮдҪ е°ҶиҝҷдәӣеӯҳеӮЁеңЁе“ӘдёӘж•°жҚ®еә“дёӯпјҹ - Matt Johnson-Pint
哎呀!你关于UTC Matt的说法是正确的,但我的想法是使用本地时区和毫秒数进行转换,这应该可以给我本地时间。我正在使用MySQL。我以前没有使用过JopdaTime,但肯定会考虑这个解决方案。如果我存储事件创建者的本地日期时间和时区,那么在转换为查看者的日期时间时,是否会遇到问题? - user2754571
那应该没问题,只要像我描述的那样注意夏令时问题就可以了。 - Matt Johnson-Pint
显示剩余9条评论

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