tz.inDaylightTime(new Date())为时区GMT + 8返回true为ID: - Asia / Choibalsan哪个错了

时间:2016-04-06 12:32:22

标签: java date timezone

TimeZone问题: - 北京,重庆,香港,乌鲁木齐(格林威治标准时间8)

在调试中获取上述时区的ID  : - [南极洲/凯西,亚洲/文莱,亚洲/赤塔,亚洲/乔巴山, 亚洲/重庆,亚洲/重庆,亚洲/哈尔滨,亚洲/ Hong_Kong, 亚洲/伊尔库茨克,亚洲/ Kuala_Lumpur,亚洲/古晋,亚洲/澳门, 亚洲/澳门,亚洲/望加锡,亚洲/马尼拉,亚洲/上海, 亚洲/新加坡,亚洲/台北,亚洲/ Ujung_Pandang,亚洲/乌兰巴托, Asia / Ulan_Bator,Australia / Perth,Australia / West,CTT,Etc / GMT-8,Hongkong,PRC,Singapore]

问题:-tz.inDaylightTime(new Date())为id Asia / Choibalsan 返回true  并给予3600000日光差异。因为它显示时间提前1小时到香港用户。因为它增加了3600000作为日间节能差异

这是错误的,因为在香港时区没有夏令时。 “tz.inDaylightTime()”应该在这里返回false。

这是在linux服务器JDK8上开始生产的。

它正在使用JDK8在Windows上的本地系统上工作。

我的参考代码: -

public static String setDateTimeInTimezone(Date date, String userTimeZone) {
    int offset = parseTimeZone(userTimeZone);
    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    int timezoneDSTSaving = 0;
    String[] timeArray = TimeZone.getAvailableIDs(offset);
    TimeZone tz=null;
    for (int i = 0; i < timeArray.length; i++) {
        tz = TimeZone.getTimeZone(timeArray[i]);
        if (tz.inDaylightTime(new Date())) {
            timezoneDSTSaving = tz.getDSTSavings();
        }
        if (timezoneDSTSaving != 0) {
            break;
        }
    }
    //formatter.setTimeZone(tz);
    return formatter.format(new Date(date.getTime() + offset + timezoneDSTSaving));
}

public static int parseTimeZone(String userTimeZone) {
    // Represent GMT String used to display user time zone.
    final String gmtStringConstant = GMT_OFFSET_STRING;
    // Represent 60 minute in a hour.
    final int minutes = 60;
    // Represent 60 seconds in minute.
    final int seconds = 60;
    // Represent 1000 milli seconds in second.
    final int milliseconds = 1000;
    int timezoneDifference = 0;
    int gmtIndex = userTimeZone.indexOf(gmtStringConstant);
    // If "(GMT" String is not found in timezone, return 0.
    if (gmtIndex == -1) {
        return timezoneDifference;
    }
    String timeZone = userTimeZone.substring(gmtIndex + gmtStringConstant.length(), userTimeZone.length() - 1);
    int indexOfColon = timeZone.indexOf(":");
    if (indexOfColon != -1) {
        int hourDiff = Integer.parseInt(timeZone.substring(0, indexOfColon)) * minutes * seconds * milliseconds;
        int minDiff = Integer.parseInt(timeZone.substring(indexOfColon + 1)) * seconds * milliseconds;
        if (hourDiff < 0) {
            minDiff *= -1;
        }
        timezoneDifference = hourDiff + minDiff;
    } else {
        timezoneDifference = Integer.parseInt(timeZone) * minutes * seconds * milliseconds;
    }
    return timezoneDifference;
}

注意:我不想使用ZODATIME我只想处理工具日期

1 个答案:

答案 0 :(得分:1)

tl; dr

  • DST在Asia/Choibalsan中一直有效,直到2016年9月23日停止遵守。现在,全年偏移量为+08:00。
  • 您使用的可怕的日期时间类现在应该避免。

java.time

注意:我不想使用ZODATIME,我只想处理使用日期

可怕的java.util.Date类在多年前被JSR 310所采用的现代 java.time 类所取代。

将所需的时区指定为ZoneId对象。

ZoneId z = ZoneId.of( "Asia/Choibalsan" ) ;

获取该区域的规则,该区域人民使用的偏移的过去,现在和将来的历史记录。获取一个ZoneRules对象。

ZoneRules rules = z.getRules() ;

指定一个时刻,我们要确定DST是否生效。您是在16年4月6日12:32问这个问题的,所以让我们利用这一时刻。

LocalDate ld = LocalDate.of( 2016 , Month.APRIL , 6 ) ;
LocalTime lt = LocalTime.of( 12 , 32 ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

zdt.toString():

通过提取Instant来适应UTC。

Instant instant = zdt.toInstant() ;  // Extract a `Instant`, adjusting from time zone to UTC.

此时在该区域询问if DST was in effect

boolean inDst = rules.isDaylightSavings​( instant ) ;

并询问DST调整的金额是多少(如果DST有效)。

Duration d = rules.getDaylightSavings​( instant ) ;

请参见code run live at IdeOne.com

zdt.toString():2016-04-06T12:32 + 09:00 [Asia / Choibalsan]

instant.toString():2016-04-06T03:32:00Z

inDst.toString():是

我们得到的结果是,Asia/Choibalsan时刻确实在DST中。

让我们尝试一下当前时刻。

System.out.println(
    ZoneId
    .of( "Asia/Choibalsan" )
    .getRules()
    .isDaylightSavings( 
        Instant.now() 
    )
);

我们在DST中得到false不是。这与the report by Time.is网站(目前尚不在DST中)一致,同时还声称+08:00Asia/Choibalsan的全年偏移量。

DST在2016-09-23之后下降了Asia/Choibalsan

这些结果与report by this site一致,该日期是在该时区,DST的最后一次转换是在2016年9月23日,因此DST的遵守时间已降低。