Java 如何知道一个国家是否有夏时制?

Java 如何知道一个国家是否有夏时制?,java,timezone,dst,Java,Timezone,Dst,我有一个时区值列表,就像我们在Windows操作系统时区下拉列表中看到的一样 如果我们在下拉列表中选择任何时区,就可以知道是否存在夏令时 如何实现类似的功能?目前,我有一个类似的值列表,就像我们在Windows下拉列表中看到的一样 我知道TimeZone对象将解决这个问题,因为它有一个布尔属性来说明是否存在夏令时。但是我对如何使用可用的值列表创建时区对象感到非常困惑 我有如下下拉值: (UTC-12:00)国际日期线西行 (UTC-11:00)协调世界时-11 (UTC-10:00)阿留申群岛

我有一个时区值列表,就像我们在Windows操作系统时区下拉列表中看到的一样

如果我们在下拉列表中选择任何时区,就可以知道是否存在夏令时

如何实现类似的功能?目前,我有一个类似的值列表,就像我们在Windows下拉列表中看到的一样

我知道
TimeZone
对象将解决这个问题,因为它有一个
布尔属性来说明是否存在夏令时。但是我对如何使用可用的值列表创建
时区
对象感到非常困惑

我有如下下拉值:

  • (UTC-12:00)国际日期线西行
  • (UTC-11:00)协调世界时-11
  • (UTC-10:00)阿留申群岛
  • (UTC-10:00)夏威夷
  • (UTC-09:30)马奎萨斯群岛

有了上面的示例值,我如何创建
时区
对象?

您可以按照问题注释中的建议尝试使用时区

String zone = "(UTC-12:00) International Date Line West";

String zoneID = "GMT";
zoneID = zoneID + zone.substring(zone.indexOf("-"), zone.indexOf(")"));
System.out.println(zoneID);
TimeZone timeZone = TimeZone.getTimeZone(zoneID);
boolean answer = timeZone.observesDaylightTime();
System.out.print(answer);
您可以尝试使用数组列表来迭代所有值,而不是像我一样使用字符串。时区接受区域ID的格式,如中所示

更新

UTC不使用DST(来源:),因此您必须将UTC转换为目标时区或使用类似zoneID=“America/New_York”的城市名称。 更新代码:

ZoneId zd = ZoneId.of(zoneID);
System.out.println(zd.getId());
ZonedDateTime zdt = ZonedDateTime.of(
        LocalDateTime.of(LocalDate.of(2018, 4, 12), LocalTime.of(11, 30)), zd);
Instant instant = zdt.toInstant();
ZoneRules zr = zd.getRules();
System.out.println(zr.isDaylightSavings(instant));
上面的代码使用Java8时间类。另外,我在四月份使用了
LocalDate
,因为在大多数观察到DST的国家,它会在三月份的某个时候应用。

这是一项艰巨的任务。在“时区数据库”部分,您将看到Windows时区名称与Iana/Olson数据库(Java使用的)中的时区名称非常不同

在Java中,您可以使用
TimeZone.getAvailableIDs()
,或者
ZoneId.getAvailableZoneIds()
(如果您有Java 8),查看所有可用名称,并查看它们与Windows时区列表的不匹配情况

我认为最好的方法是将每个Windows名称映射到一个有效的Iana名称,要知道并不是所有情况都完全匹配:Iana数据库更完整、更准确,特别是夏令时数据,包括历史数据,而且更新频率比Windows更高

而且名称也非常不同,Iana更全面,有更多的名称-一个Windows时区名称可以指的是来自Iana的多个名称。我不确定是否有一种简单的方法可以将所有名字从一个映射到另一个

但一旦你有了这些名字,就很容易检查:

TimeZone zone = TimeZone.getTimeZone("America/New_York");
// check if it has DST now or in the future (doesn't check the past)
boolean hasDST = zone.observesDaylightTime();

// check if a specific date is in DST
Date someDate = // some java.util.Date
boolean dateInDST = zone.inDaylightTime(someDate);
在Java 8中:

ZoneRules rules = ZoneId.of("America/New_York").getRules();

// if it has DST, isFixed is false
boolean isFixed = rules.isFixedOffset();

// if lists are empty, offset never varies, so there's no DST
List<ZoneOffsetTransitionRule> transitionRules = rules.getTransitionRules();
List<ZoneOffsetTransition> transitions = rules.getTransitions();

// check a specific date (using java.time.Instant)
rules.isDaylightSavings(Instant.now());
// check a specific date (using java.util.Date)
Date date = new Date();
rules.isDaylightSavings(date.toInstant());
这样,您就可以知道偏移量发生变化的确切日期。 有些时区没有转换,但它们有转换规则(例如“DST在11月的第一个星期日开始”)。在这种情况下,将使用转换规则列表:

rules.getTransitionRules().forEach(r -> {
    // check the rule for a specific year
    ZoneOffsetTransition t = r.createTransition(2018);

    // UTC instant that the change happens
    Instant instant = t.getInstant();

    // local date and time before the change
    LocalDateTime before = t.getDateTimeBefore();

    // local date and time after the change
    LocalDateTime after = t.getDateTimeAfter();
});

您可以查看和/或和/或您可以创建一个
时区
,通过和/或Thnaks进行响应,是的,我已经看到使用zoneID我们可以创建对象。但如果我们有像OS dropDwon这样的价值观呢?我们如何创建时区?您需要确定您拥有的信息是否可以映射到
时区
输入的要求,如果不能,您需要弄清楚如何将您拥有的信息映射到API的要求。您在该列表中显示的值是显示名称,而不是标识符。它们由Windows按语言进行本地化。您根本不应该在应用程序中使用它们。String zone=“(UTC-10:00)阿留申群岛”;答案是像假一样给出,这是不正确的。DaylightTime已存在。抱歉,我忘了将UTC更改为函数可识别的GMT。我知道日光节约只在三月份开始,inDaylightTime也会告诉你它现在是否遵守日光节约时间。更新我的答案。感谢您的回复,但仍然是字符串zone=“(UTC-10:00)阿留申群岛”;答案是false,这是不正确的。
TimeZone
类早已过时。请不要教年轻人使用它。相反,我建议使用它的
ZoneId
class.@OleV.V。我实际上是在用
java.time
:)更新我的答案;谢谢用于Windows和IANA时区之间的映射。
rules.getTransitionRules().forEach(r -> {
    // check the rule for a specific year
    ZoneOffsetTransition t = r.createTransition(2018);

    // UTC instant that the change happens
    Instant instant = t.getInstant();

    // local date and time before the change
    LocalDateTime before = t.getDateTimeBefore();

    // local date and time after the change
    LocalDateTime after = t.getDateTimeAfter();
});