我有一个时区值列表,就像我们在Windows操作系统时区下拉列表中看到的那样。
如果我们在下拉列表中选择任何时区,我们就会知道是否存在夏令时。
我怎样才能实现这种类似功能?目前,我有一个类似的值列表,就像我们在Windows下拉列表中看到的那样。
我了解TimeZone
对象将解决此问题,因为它具有boolean
属性,用于说明是否存在夏令时。但我对如何使用可用的值列表创建TimeZone
对象感到困惑。
我有下面的下拉值:
使用上面的示例值,我如何创建TimeZone
对象?
答案 0 :(得分:2)
这是一项艰巨的任务。在this link,在"时区数据库" 部分,您会看到Windows时区名称与Iana / Olson数据库中的名称非常不同(是Java使用的那个。
在Java中,您可以使用TimeZone.getAvailableIDs()
或ZoneId.getAvailableZoneIds()
(如果您有Java 8)查看所有可用名称 - 并查看它们与Windows时区列表的匹配程度。
我认为你能做的最好的事情就是将每个Windows名称映射到一个有效的Iana名称,知道所有情况都不匹配:Iana数据库更加完整和准确,特别适用于Daylight保存数据,包括历史数据 - 并且比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。这可能只是一个简单的改变:政府决定永久地改变国家的抵消和#34; - 这意味着&#34;直到其他政治家决定再次改变它为止#34;。
夏令时只是抵消变更的一个特例,并且无法知道这种变化是否与DST相关 - 例如当一个国家决定改变某些偏移并且不使用DST时;该区域仍然是非固定的(isFixedOffset
返回true
),因为偏移已更改。
在这种情况下,您可以使用转换列表来了解何时发生这些更改:
rules.getTransitions().forEach(t -> {
// 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();
});
通过此,您可以知道具有偏移更改的确切日期。 有些时区没有转换,但是它们有转换规则(例如&#34; DST从11月的第一个星期日开始,#34;)。在这种情况下,您使用转换规则列表:
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();
});
答案 1 :(得分:1)
您可以按照问题的评论中的建议尝试使用TimeZone。
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);
您可以尝试使用数组列表来迭代所有值,而不是像我一样使用字符串。时区按照https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html
中所示的格式接受区域ID<强>更新强>
UTC不使用DST(来源:https://en.wikipedia.org/wiki/Coordinated_Universal_Time),因此您必须将UTC转换为目标时区或使用城市名称,例如zoneID =&#34; America / New_York&#34 ;。 更新的代码:
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));
上面的代码使用java 8时间类。此外,我在4月份使用了LocalDate
,因为在大多数观察到夏令时的国家,它会在3月的某个地方应用。