webapp中的时区问题

时间:2014-06-03 12:41:03

标签: java web-applications timezone

我想知道在网络应用中处理时区的最佳做法。 举个例子,Server是UTC时区,user1和user2都在不同的时区。什么是处理日期的正确方法?

  1. 当user1添加新日期时,它位于不同的时区,Server是UTC格式,那么我应该将日期转换为UTC并存储在数据库中吗?

  2. 显示UTC格式的日期获取日期,然后根据客户端时区进行转换并显示。这是正确的方式吗?

  3. 什么是DST问题?它会影响这个过程吗?

  4. 在某个地方,我只读了mili秒的商店日期是个好主意吗?现在我将其存储为日期/时间。

  5. 有没有适当的方法或库,请建议

  6. 我的问题是

    GMT +5:30的客户创建记录并设置交付日期和时间让我们说2014年6月30日晚上11:30 GMT +5:30

    所以GMT -3:00的运输商可以在GMT -3:00中看到客户选择的确切当地时间。怎么做到这一点?

1 个答案:

答案 0 :(得分:7)

1

是。通常,最佳做法是将所有日期时间值存储在UTC中。您的业​​务逻辑应该适用于UTC

您可能还希望将用户输入的值或外部数据源存储为审计跟踪或调试辅助工具。但是使用UTC作为官方记录。

是的,服务器的时区应设置为UTC(如果不可能,则使用雷克雅未克冰岛)。但是在编程中不要依赖于此。在代码中指定所需的时区,而不是依赖默认值。

2

是。转换为本地化的演示时间。当然,除非用户更喜欢UTC。

将其视为本地化的一部分。进行国际化时,可以使用代码中的键值。然后在演示时,您使用键值来查找要显示给用户的本地化翻译字符串。

3

非问题。如果“DST”表示夏令时,则使用体面的日期时间库将自动处理夏令时的调整。警告:您需要保持图书馆使用的时区定义列表是最新的,因为政府经常更改规则。

如果调整DST(或时区)会导致您的用户产生混淆或错误信息,那么您应该在这种情况下显示UTC。

4

没有。在大多数情况下,不要存储或工作毫秒。数据库和日期时间库可以在内部执行,但您不应该这样做。

一些书呆子类型会建议跟踪毫秒。但是使用日期时间作为毫秒就像使用文本作为字节数组一样。我们使用具有更高抽象级别的代码库来处理文本的所有复杂性(UTF-8,变音符号的Unicode规范化等)并添加有用的方法(搜索,替换等)。所以它与日期时间有关。

此外,使用毫秒将导致混淆并使调试变得困难,因为您无法轻易理解其价值。 日期工作本质上很棘手且容易出错。使用毫秒没有用。

并非所有数据库和其他库都在内部使用毫秒。有些使用整秒,或微秒,或纳秒。它们也没有使用相同的epoch

5

在Java中,我们有两个很好的日期时间库:Joda-Timejava.time(Java 8)。

java.time包的灵感来自Joda-Time,但是经过重新设计。他们有相似的概念,但不完全相同。只要您对import语句小心谨慎,就可以在代码中使用它们。两者都有各自的优点和缺点。

避免使用j.u.Date/.Calendar

不要使用与Java捆绑在一起的java.util.Date和.Calendar类。众所周知,它们在设计和实施方面都很麻烦,存在缺陷。它们已经被Sun / Oracle取代了新的java.time包。

当一些其他类需要j.u.Date对象时,Joda-Time和java.time都包含了一些方便的方法来转换为java.util.Date对象。

奖金提示

关于文字格式:

  • 避免使用您在问题中使用的字符串格式。它难以理解,难以解析。
  • 了解如何使用ISO 8601 standard定义的各种字符串格式作为日期时间值的文本表示。
  • 不要像在你的问题中那样在偏移中丢弃前导零。这将破坏库中的代码,并违反标准要求。始终写+05:30从不 +5:30。即使在写散文时也要养成这种习惯,而不仅仅是编程代码。

示例代码

使用Joda-Time 2.3的示例代码。

实例化日期时间,本地到+05:30偏移量。我任意选择加尔各答时区。你当然会用适当的替换。

DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeKolkata = new DateTime( 2014, DateTimeConstants.JUNE, 30, 23, 30, 0, timeZoneKolkata );

使用-03:00偏移将相同时刻调整到另一个时区。我随意选择了America / Buenos_Aires。

DateTimeZone timeZoneBuenos_Aires = DateTimeZone.forID( "America/Buenos_Aires" );
DateTime dateTimeBuenos_Aires = dateTimeKolkata.withZone( timeZoneBuenos_Aires );

转换为UTC。

DateTime dateTimeUtc = dateTimeKolkata.withZone( DateTimeZone.UTC );