tz.inDaylightTime(new Date())为时区GMT+8返回true,ID为:-亚洲/Choibals



时区问题: -北京、重庆、香港、乌鲁木齐(GMT 8)

在调试中获取上述时区的Id:- [南极洲/凯西,亚洲/文莱,亚洲/赤塔,亚洲/乔伊巴尔桑,亚洲/重庆,亚洲/重庆、亚洲/哈尔滨、亚洲/香港,亚洲/伊尔库茨克,亚洲/吉隆坡,亚洲/古晋,亚洲/澳门,亚洲/澳门、亚洲/望加锡、亚洲/马尼拉、亚洲/上海,亚洲/新加坡、亚洲/台北、亚洲/乌戎班当、亚洲/乌兰巴托,亚洲/澳大利亚乌兰巴托/澳大利亚珀斯/西部,CTT,Etc/GMT-8,中国香港,新加坡]

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

这是错误的,因为香港时区没有夏令时。"tz.inDaylightTime()"应在此处返回false

这个issue即将在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,我只想用util日期处理

tl;dr

  • 夏令时在Asia/Choibalsan一直有效,直到2016年9月23日停止遵守。现在全年的偏移量是+08:00
  • 您正在使用糟糕的日期-时间类,现在应该避免使用这些类

java.time

注意:我不想使用ZODATIME,我想用util-date-only 处理

可怕的java.util.Date类在几年前被现代的java.time类所取代,直到JSR310被采用。

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

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

获取该区域的规则,该区域人民使用的偏移量的过去、现在和未来变化的历史。获取一个ZoneRules对象。

ZoneRules rules = z.getRules() ;

指定要确定夏令时是否有效的时刻。你在2016年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.

询问夏令时当时是否在该区域生效。

boolean inDst = rules.isDaylightSavings​( instant ) ;

并询问夏令时调整的金额(如果夏令时生效)。

Duration d = rules.getDaylightSavings​( instant ) ;

请参阅IdeOne.com上实时运行的代码。

zdt.toString():2016-04-06T12:32+09:00〔亚洲/乔伊巴尔桑〕

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

inDst.toString():真正的

我们得到的结果是,Asia/Choibalsan此时确实处于夏令时。

让我们试试当下。

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

我们得到false而不是当前处于夏令时。这与Time.is网站的报告一致,该网站目前未处于夏令时,同时也声称+08:00Asia/Choibalsan的全年补偿。

Asia/Choibalsan在2016-09-23之后降低夏令时

这些结果与该网站的报告一致,即夏令时在该时区的遵守情况有所下降,最后一次夏令时转换发生在2016年9月23日。

最新更新