国家/地区的时区,夏令时是否有效



请考虑以下代码:

if(strTimeZoneCd.equals("A"))
locTz = TimeZone.getTimeZone("AST");
else if(strTimeZoneCd.equals("M"))
locTz = TimeZone.getTimeZone("MST");
else if(strTimeZoneCd.equals("P"))
locTz = TimeZone.getTimeZone("PST");
else if(strTimeZoneCd.equals("H"))
locTz = TimeZone.getTimeZone("HST");
else if(strTimeZoneCd.equals("C"))
locTz = TimeZone.getTimeZone("CST");
else if(strTimeZoneCd.equals("E"))
locTz = TimeZone.getTimeZone("EST");
else if(strTimeZoneCd.equals("G"))
locTz = TimeZone.getTimeZone("GMT");
else if(strTimeZoneCd.equals("Y"))
locTz = TimeZone.getTimeZone("AKST");

在这里,如果我通过A,它会给我AST。但取而代之的是,我需要确定我应该返回AST还是ADT.

我需要确定AST现在是否处于夏令时状态。如果是夏令时,我可以返回ADT,如果不是,我可以返回AST.但是我不知道如何确定该时区是否在夏令时。

有人可以帮我吗?

首先,避免使用时区名称的简短缩写(如CSTPSTCEST),因为它们是模棱两可的,不是标准的。

例如,CST被多个时区使用:它可以是"中部标准时间"、"中国标准时间"或"古巴标准时间"。而且每个人都有不同的关于Dayligh节省时间的规则,因此使用缩写不一定能得到你期望的结果。

TimeZone类假定这些短名称的一些默认值(所有任意选择,就像任何默认值一样),并且还具有在名称未知时返回 GMT 的奇怪行为。

为避免这些歧义,最好使用 IANA 时区名称(始终采用Region/City格式,如Asia/KolkataAmerica/New_York)。

您可以通过调用TimeZone.getAvailableIDs()来获取可用时区的列表(并选择最适合您系统的时区)。

然后,您可以使用inDaylightTime()方法,如其他答案中所述。

另一种方法是使用格式化程序,因为它会自动检查它是否在夏令时并打印区域短名称。我还使用java.util.Locale来指示名称应为英文(我不确定不同的语言是否会影响短区名称,这是一种"以防万一"的方法):

// formatter with `z` (zone short name)
SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.ENGLISH);
// set timezone in the formatter
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
// prints the zone name for the current date
System.out.println(sdf.format(new Date()));

上面的代码打印EDT(因为今天,2017 年 9 月 13,纽约处于夏令时,使用的缩写是 EDT)。

在这种情况下,您可以创建格式化程序,并使用if逻辑在其中设置正确的时区。然后,格式化程序负责检查日期是否在夏令时,返回正确的缩写。


Java new Date/Time API

旧的类(DateCalendarSimpleDateFormat)有很多问题和设计问题,它们正在被新的API所取代。

如果您使用的是Java 8,请考虑使用新的 java.time API。它比旧的 API 更容易、更少错误且更不容易出错。

如果你使用的是Java<= 7,你可以使用ThreeTen Backport,这是Java 8新的日期/时间类的一个很好的反向移植。对于Android,您还需要ThreeTenABP(更多有关如何使用它的信息)。

下面的代码适用于这两种情况。 唯一的区别是包名(在Java 8中是java.time,在ThreeTen Backport(或Android的ThreeTenABP)中是org.threeten.bp),但类和方法名称是相同的。

首先,我创建一个具有z模式(对应于区域短名称)和英语区域设置的DateTimeFormatter

然后我使用ZonedDateTime,它表示特定时区中的日期和时间,以及获取当前日期/时间的now()方法。我还使用ZoneId来指定我想要的时区:

// create formatter for short zone name and English locale
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("z", Locale.ENGLISH);
// format current date in New York timezone
System.out.println(fmt.format(ZonedDateTime.now(ZoneId.of("America/New_York"))));

这也打印EDT。您可以应用上述相同的if逻辑来定义将在ZoneId.of()中使用哪个时区。只是提醒不要使用短名称(CST等),因为新 API 不像旧 API 那么宽松。

TimeZone假设有很多任意默认值,并在区域不存在时返回"GMT",但如果尝试获取无效区域,ZoneId会引发异常(某些缩写应该适用于逆向兼容性原因,但默认值也是任意的,您应该避免它们)。


区域名称的自定义映射

您可以选择创建时区名称的自定义映射,因此无需创建大量if子句来确定相应的区域。像这样:

// create custom map of zone names
Map<String, String> customZones = new HashMap<>();
// map "E" to New York
customZones.put("E", "America/New_York");
// map "G" to GMT
customZones.put("G", "GMT");
...
// create timezone using the custom map ("E" will create "America/New_York" zone)
ZoneId zone = ZoneId.of("E", customZones);
// format current date in specified timezone
System.out.println(fmt.format(ZonedDateTime.now(zone)));

解决此问题:

对于任何特定时区

TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());

您可以使用此程序来确定该时区是否处于夏令时之下。

另请参阅此链接。

TimeZone.getTimeZone("CST") 返回 GMT

import java.util.Date;
import java.util.TimeZone;
public class test {
public static void main(String[] args) {
System.out.println(TimeZone.getTimeZone("EST").inDaylightTime( new Date() ));
System.out.println(TimeZone.getTimeZone( "GMT-9:00").inDaylightTime( new Date() ));
}
}

最新更新