64

我必须在我的 Java 应用程序中打印 EST 时间。我已使用以下方法将时区设置为 EST:

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

但是当在这个时区遵循夏令时时,我的代码不会打印正确的时间(它打印的时间少 1 小时)。

无论是否遵守夏令时,如何使代码始终读取正确的时间?

PS:我尝试将时区设置为 EDT,但并没有解决问题。

4

8 回答 8

115

这是开始的问题:

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

应完全避免使用 3 个字母的缩写,以支持 TZDB 区域 ID。EST 是东部标准时间 -标准时间从不遵守 DST;这不是一个完整的时区名称。它是用于部分时区的名称。(不幸的是,我还没有找到一个关于“半时区”概念的好词。)

您想要一个完整的时区名称。例如,America/New_York在东部时区:

TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);

System.out.println(format.format(new Date()));
于 2012-05-11T05:50:41.000 回答
22

其他答案是正确的,尤其是Jon Skeet 的答案,但已经过时了。

java.time

这些旧的日期时间类已被Java 8 及更高版本中内置的java.time框架所取代。

如果您只是想要 UTC 的当前时间,请使用Instant该类。

Instant now = Instant.now();

EST不是时区,正如Jon Skeet 的正确答案中所解释的那样。这样的 3-4 个字母代码既不标准化也不唯一,进一步混淆了夏令时 (DST)。使用“大陆/地区”格式的正确时区名称。

也许您的意思是北美东海岸的东部标准时间?还是埃及标准时间?还是欧洲标准时间?

ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );

使用任何此类ZoneId对象将当前时刻调整到特定时区以生成ZonedDateTime对象。

ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

通过从第一个对象生成另一个 ZonedDateTime 对象,将该 ZonedDateTime 调整到不同的时区。java.time 框架使用不可变对象而不是更改(变异)现有对象。

ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;

Java 中的日期时间类型表,包括现代和传统。

于 2016-01-05T01:33:02.183 回答
4

您可以输入“EST5EDT”,而不是输入“EST”作为时区。正如您所指出的,仅“EDT”不起作用。这将解决夏令时问题。代码行如下所示:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
于 2016-09-07T13:58:13.943 回答
1

根据这个答案

TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());
于 2015-12-14T18:55:28.767 回答
1
private static Long DateTimeNowTicks(){
    long TICKS_AT_EPOCH = 621355968000000000L;
    TimeZone timeZone = Calendar.getInstance().getTimeZone();
    int offs = timeZone.getRawOffset();
    if (timeZone.inDaylightTime(new Date()))
        offs += 60 * 60 * 1000;
    return (System.currentTimeMillis() + offs) * 10000 + TICKS_AT_EPOCH;
}
于 2018-10-15T14:58:00.767 回答
0
public static float calculateTimeZone(String deviceTimeZone) {
    float ONE_HOUR_MILLIS = 60 * 60 * 1000;

    // Current timezone and date
    TimeZone timeZone = TimeZone.getTimeZone(deviceTimeZone);
    Date nowDate = new Date();
    float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;

    // Daylight Saving time
    if (timeZone.useDaylightTime()) {
        // DST is used
        // I'm saving this is preferences for later use

        // save the offset value to use it later
        float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
        // DstOffsetValue = dstOffset
        // I'm saving this is preferences for later use
        // save that now we are in DST mode
        if (timeZone.inDaylightTime(nowDate)) {
            Log.e(Utility.class.getName(), "in Daylight Time");
            return -(ONE_HOUR_MILLIS * dstOffset);
        } else {
            Log.e(Utility.class.getName(), "not in Daylight Time");
            return 0;
        }
    } else
        return 0;
}
于 2018-07-26T09:45:42.543 回答
-1

在java中,DateFormatter默认使用DST,为了避免夏令时(DST)你需要手动做一个技巧,
首先你必须得到DST偏移量,即应用了多少毫秒的DST,例如某处DST也是45分钟对于某些地方,它是 30 分钟
,但在大多数情况下,DST 是 1 小时
,您必须使用 Timezone 对象并检查日期是否属于 DST,然后您必须手动将 DST 的偏移量添加到其中。例如:

 TimeZone tz = TimeZone.getTimeZone("EST");
 boolean isDST = tz.inDaylightTime(yourDateObj);
 if(isDST){
 int sec= tz.getDSTSavings()/1000;// for no. of seconds
 Calendar cal= Calendar.getInstance();
 cal.setTime(yourDateObj);
 cal.add(Calendar.Seconds,sec);
 System.out.println(cal.getTime());// your Date with DST neglected
  }
于 2016-01-04T17:40:01.413 回答
-3

实现 TimeZone 类以将时区设置为 Calendar 负责夏令时。

java.util.TimeZone 表示时区偏移量,还计算夏令时。

示例代码:

TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone();
Calendar enteredCalendar = Calendar.getInstance();
enteredCalendar.setTimeZone(est_timeZone);
于 2014-08-08T05:34:25.340 回答