一个国家的时区,是否实行夏令时

Time zone of a country, whether day light savings is in effect

考虑以下代码:

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。但是我需要确定我是否应该 return ASTADT.

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

有人可以帮我吗?

解决这个问题:

对于任何特定时区

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

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

另请参阅此 link。

TimeZone.getTimeZone("CST") returns 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() ));
    }
}

首先,避免使用时区名称的缩写(如 CSTPSTCEST),因为它们是 ambiguous and not standard.

CST,例如,被more than one timezone: it can be "Central Standard Time", "China Standard Time" or "Cuba Standard Time”使用。而且每个人对夏令时都有不同的规定,所以使用缩写不一定能得到你期望的结果。

TimeZone class 假定这些短名称的一些默认值(所有任意选择,任何默认值都是如此)并且还具有 returning GMT when the name is unknown.[=51= 的奇怪行为]

为避免这些歧义,最好使用 IANA timezones names(始终采用 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 日,纽约正处于夏令时和abbreviation used is EDT)。

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


Java新Date/TimeAPI

旧的 classes(DateCalendarSimpleDateFormat)有 lots of problems and design issues,它们正在被新的 APIs.

如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.

如果您使用 Java <= 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it ).

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

首先,我使用 z 模式(对应于区域短名称)和英语语言环境创建了一个 DateTimeFormatter

然后我用一个ZonedDateTime,代表一个特定时区的日期和时间,用now()方法得到当前的date/time。我还使用 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 不像旧的那么宽松。

当区域不存在时,

TimeZone 假定许多任意默认值和 returns“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)));