Java:计算时区差异

时间:2013-04-03 13:37:42

标签: java timezone dst

如何在Java中获取GMT与特定日期和时区的时差?

确定特定时区是否在DST中非常简单:

boolean isIsraelInDST = TimeZone.getTimeZone("Israel").inDaylightTime(new Date());

如何获得实际时差?

5 个答案:

答案 0 :(得分:21)

使用TimeZone.getRawOffset():返回添加到UTC以获取此时区的标准时间的时间量(以毫秒为单位)。由于此值不受夏令时影响,因此称为原始偏移

如果您想要包含DST的偏移量,则使用TimeZone.getOffset(长日期)。您应该为方法提供具体日期,例如now - System.currentTimeMillis()

答案 1 :(得分:9)

我建议将夏季/冬季时间偏移量添加到getRawOffset:

    TimeZone tz1 = TimeZone.getTimeZone("GMT");
    TimeZone tz2 = TimeZone.getTimeZone("America/New_York");
    long timeDifference = tz1.getRawOffset() - tz2.getRawOffset() + tz1.getDSTSavings() - tz2.getDSTSavings();

答案 2 :(得分:7)

我看到这是一个旧线程 - 但是因为我最近有类似的要求而添加了这个 - 这给出了基于CURRENT时间(毫秒来自纪元)的毫秒的实际差异。

    TimeZone.getTimeZone("America/New_York").getOffset(Calendar.getInstance().getTimeInMillis())

答案 3 :(得分:7)

TL;博士

ZoneId.of( "Pacific/Auckland" )   // Specify a time zone.
    .getRules()                   // Get the object representing the rules for all the past, present, and future changes in offset used by the people in the region of that zone.
    .getOffset( Instant.now() )   // Get a `ZoneOffset` object representing the number of hours, minutes, and seconds displaced from UTC. Here we ask for the offset in effect right now.
    .toString()                   // Generate a String in standard ISO 8601 format.
  

13:00

某某日期的第一时刻。

ZoneId.of( "Pacific/Auckland" )
    .getRules()
    .getOffset( 
        LocalDate.of( 2018 , Month.AUGUST , 23 )          // Specify a certain date. Has no concept of time zone or offset.
        .atStartOfDay( ZoneId.of( "Pacific/Auckland" ) )  // Determine the first moment of the day on that date in that region. Not always `00:00:00` because of anomalies such as Daylight Saving Time.
        .toInstant()                                      // Adjust to UTC by extracting an `Instant`. 
    ) 
    .toString()
  

12:00

避免遗留日期时间类

其他答案已经过时了,因为TimeZone类现已成为遗产。这个和其他麻烦的旧日期时间类被 java.time 时间类所取代。

java.time

现在我们使用ZoneIdZoneOffsetZoneRules代替遗留TimeZone类。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;  

获取该区域的规则。

ZoneRules rules = z.getRules() ;

如果夏令时(DST)在某个时刻生效,请询问规则。将时刻指定为InstantInstant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instant = Instant.now() ;  // Capture current moment in UTC.
boolean isDst = rules.isDaylightSavings( instant ) ;
  

如何获得实际时差?

不确定你的意思,但我猜你在那个时刻要求offset-from-UTC生效。偏移量是UTC的小时,分​​钟和秒位移数。我们使用ZoneOffset类表示偏移量。时区是特定地区人民使用的偏移的过去,现在和将来变化的历史。我们使用ZoneId类表示时区。

因为某个地区的偏移可能会随时间而变化,所以我们必须在要求偏移时过一会儿。

ZoneOffset offset = rules.getOffset( instant ) ;

生成一个字符串,表示ISO 8601标准格式的偏移量。

String output output = offset.toString() ;

您可以要求将偏移量作为总秒数。

int offsetInSeconds = offset.getTotalSeconds() ;

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

使用符合JDBC driver或更高版本的JDBC 4.2,您可以直接与数据库交换 java.time 对象。不需要字符串也不需要java.sql。* classes。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 4 :(得分:2)

public String timeZone(Date date) {
    TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
    long millis = timeZone.getRawOffset() + (timeZone.inDaylightTime(date) ? timeZone.getDSTSavings() : 0);

    return String.format("%s%s:%s",
            millis < 0 ? "-" : "+",
            String.format("%02d", Math.abs(TimeUnit.MILLISECONDS.toHours(millis))),
            String.format("%02d", Math.abs(TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))))
    );
}