【问题标题】:Java Current Date/Time displays 1 hour ahead that original timeJava 当前日期/时间显示比原始时间提前 1 小时
【发布时间】:2014-01-15 23:46:23
【问题描述】:

当我尝试使用日历实例打印当前日期和时间时,我得到的结果比实际时间提前 1 小时。

我正在使用 EST 时区运行的远程机器上工作。以下是我尝试过的,但没有任何效果。

Calendar cal = Calendar.getInstance(TimeZone.getDefault());
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
Calendar cal = Calendar.getInstance(Locale.ENGLISH);

System.out.println("Current Date & Time: " +calendar.getTime());

o/p:
Time: Sat Dec 28 11:55:10 UTC 2013

But expected o/p: 
Time: Sat Dec 28 10:55:10 UTC 2013

所有 3 种类型都给出相同的结果。我无法理解我错过了什么以获得确切的日期和时间。这个问题与夏令时有关吗?

谁能帮我解决这个问题。提前致谢。

【问题讨论】:

    标签: java date datetime


    【解决方案1】:

    这又是 java.util.Date 的老陷阱:它的 toString() 方法,您在打印 calendar.getTime() 时间接使用它使用您的默认时区,而不是您的日历实例的时区(您设置为'EST')。

    解决方案:

    Date currentTime = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
    sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
    System.out.println("Current Date & Time: " + sdf.format(currentTime));
    

    说明:

    a) 在第一行中,不需要日历实例,因为您只对当前的全球时间(独立于时区的相同物理时间)感兴趣。 Calendar.getInstance() 也更消耗资源。最后,两个表达式new Date()Calendar.getInstance(...).getTime() 在涉及内部状态时都没有时区引用。只有 j.u.Date 的toString()-方法使用默认时区。

    b) 您需要定义第 2 行中给出的输出格式。您可以更改它。学习java.text.SimpleDateFormat的模式文档就好了。

    c) 您还需要在输出格式中定义时区,以帮助格式对象将全局日期实例转换为时区感知表示。顺便说一句,我选择了标识符“America/New_York”,而不是“EST”,因为后一种形式有时会模棱两可。您应该选择第一种形式(IANA 或 Olson 时区标识符)或“GMT+/-HH:mm”形式。

    d) 输出本身由sdf.format(currentTime) 完成,而不仅仅是currentTime(没有隐式调用toString())。

    e) 回答您的问题“这个问题是否与夏令时有关?”:不,美国东部标准时间(美国/纽约)12 月的夏令时从不采用美国东部标准时间。

    结论:

    如果可以,您应该尽量避免使用 j.u.Date 和 j.u.Calendar,因为陷阱太多。目前 JodaTime 是一个更好的选择,尽管并非没有问题。

    【讨论】:

      【解决方案2】:

      避免使用 3 个字母的时区

      切勿使用 3 个字母的时区代码。它们既不是标准化的,也不是唯一的。您的“EST”至少可以表示这些:

      • 东部标准时间(美国)
      • 东部标准时间(澳大利亚)
      • 巴西东部标准时间

      使用time zone names

      避免使用 j.u.Date/Calendar

      您已经发现了避免使用与 Java 捆绑的 java.util.Date 和 java.util.Calendar 类的众多原因之一:Date 实例没有时区信息,但其 toString 方法会混淆地呈现字符串基于您的 Java 环境的默认时区。

      使用 Joda-Time

      使用合格的日期时间库。在 Java 中,这意味着 Joda-Time,或者在 Java 8 中,新的 java.time.* 类(受 Joda-Time 启发)。

      示例代码……

      // Default time zone
      DateTime dateTime_MyDefaultTimeZone = new DateTime();
      
      // Specific time zone. If by "EST" you meant east coast of United States, use a name such as New York.
      DateTimeZone timeZone = DateTimeZone.forID( "America/New_York" );
      DateTime dateTime_EastCoastUS = new DateTime( timeZone );
      

      转储到控制台...

      System.out.println( "dateTime_MyDefaultTimeZone: " + dateTime_MyDefaultTimeZone );
      System.out.println( "dateTime_EastCoastUS: " + dateTime_EastCoastUS );
      System.out.println( "date-time in UTC: " + dateTime_EastCoastUS.toDateTime( DateTimeZone.UTC ) );
      

      运行时……

      dateTime_MyDefaultTimeZone: 2013-12-28T18:51:18.485-08:00
      dateTime_EastCoastUS: 2013-12-28T21:51:18.522-05:00
      date-time in UTC: 2013-12-29T02:51:18.522Z
      

      【讨论】:

      • 仅供参考,“EST”在澳大利亚很少(并且不正确)使用。我几乎总是看到它写成“AEST”(顺便说一句,我是澳大利亚人)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多