Java当前日期/时间比原始时间提前1小时显示

时间:2013-12-28 16:24:03

标签: java date datetime

当我尝试使用Calender实例打印当前日期和时间时,我得到的结果是比实际时间提前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种类型都给出相同的结果。我无法理解我错过了什么来获得确切的日期&时间。此问题是否与夏令时有关?

有人可以帮我解决这个问题。在此先感谢。

2 个答案:

答案 0 :(得分:3)

这又是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)您还需要在输出格式中定义时区,以帮助格式对象将全局Date实例转换为时区感知表示。顺便说一句,我选择了标识符'America / New_York',而不是'EST',因为后一种形式有时可能是暧昧的。您应该选择第一个表格(IANA或Olson时区标识符)或表格'GMT +/- HH:mm'。

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

e)回答你的问题'这个问题是否与夏令时有关?':不,时区EST(America / New_York)的时间从未在12月的夏令时。

<强>结论:

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

答案 1 :(得分:0)

避免使用3个字母的时区

切勿使用3个字母的时区代码。它们既不标准也不独特。你的“EST”至少意味着:

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

使用time zone names

避免使用j.u.Date/Calendar

您已经发现了避免使用java.util.Date&amp;的众多原因之一。与Java捆绑在一起的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