一个国家的时区,无论日光节约是否有效

时间:2017-09-13 09:57:51

标签: java time timezone dst

考虑以下代码:

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

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

有人可以帮帮我吗?

3 个答案:

答案 0 :(得分:1)

解决这个问题:

对于任何特定的TimeZone

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

答案 1 :(得分:1)

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

例如,<CSTmore than one timezone使用:它可以是“Central Standard Time”,“China Standard Time”或“Cuba Standard Time”。每个人都有关于Dayligh Saving Time的不同规则,因此使用缩写可能不一定能得到您期望的结果。

TimeZone类假设这些短名称有一些默认值(所有任意选择,如任何默认选项),并且还具有returning GMT when the name is unknown的奇怪行为。

为避免这些含糊不清,最好使用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(因为今天,9月13日 th 2017,纽约处于夏令时和abbreviation used is EDT)。

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

Java新日期/时间API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,它们将被新API取代。< / p>

如果您使用的是 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs

如果您使用的是 Java&lt; = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,您还需要ThreeTenABP(更多关于如何使用它here)。

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

首先,我使用DateTimeFormatter模式(对应于区域短名称)和英语区域设置创建z

然后我使用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)));

答案 2 :(得分:0)

您可以使用此程序确定该时区是否在白天节省下。

另见此链接。

Step 11

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() ));
    }
}