带有DST的Java TimeZone

时间:2013-03-24 12:57:55

标签: java timezone dst

我有以下代码:

    public static void main(String[] args) {
       DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   //get current date time with Date()
       Date date = new Date();
       String currentDate = dateFormat.format(date);

       final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         try {
            System.out.println(sdf.format(getSomeDate(currentDate,TimeZone.getTimeZone("Asia/Omsk"))));
         } catch (ParseException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
       }  
    }

    public static Date getSomeDate(final String str, final TimeZone tz) throws ParseException {
       final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
       sdf.setTimeZone(tz);
       return sdf.parse(str);
    }

现在问题是,如果我使用我想要的时区(即“美国/芝加哥”),我会得到完全错误的时间。它当前时间为+6而不是-6。

那么我怎么能解决这个问题呢,因为现在我必须从GMT + 6开始设置一个时区以获得正确的时间和时间。我的课程的日期。

此外,Java是否自动包含DST设置?由于世界各地的人们都在使用它,所以有些人在DST时间不同,很难保持正确的时间。

2 个答案:

答案 0 :(得分:1)

java.time

现代方法使用 java.time 类。您正在使用可怕的日期时间类,这些类在几年前由于采用JSR 310而过时。

String input = "2020-01-23 15:00:00" ;

此类输入缺少时区或UTC偏移量指示符。因此,我们必须将其解析为LocalDateTime。这样的对象不是代表一个时刻,因为我们不知道您是在东京,图卢兹还是托莱多表示下午3点-彼此相隔几个小时的不同时刻。

LocalDateTime ldt = LocalDateTime.parse( input.replace( " " , "T" ) ) ;

您似乎可以确定此日期和时间是针对America/Chicago时区的。

ZoneId z = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ldt , z ) ;

让我们生成标准ISO 8601格式的字符串,以检查当时在该区域中使用的偏移量。 ZonedDateTime::toString方法明智地扩展了标准,以将区域名称附加在方括号中。

String output = zdt.toString() ;

输出:2020-01-23T15:00-06:00 [美国/芝加哥]

现在,我们在ZonedDateTime对象中确定了一个时刻。我们在时间轴上有一点说,芝加哥地区的挂钟时间似乎是下午3点。正如我们在-06:00中所看到的,这比UTC落后六个小时。

我们可以通过提取Instant对象来适应UTC。这将使一天中的时间似乎提前六个小时跳到晚上9点。时间轴上的相同时刻,相同点,但挂钟时间不同。就像两个人在冰岛(使用UTC作为时区)和芝加哥的电话上交谈一样:如果两个人同时抬头看墙上的时钟,一个人会看到3 PM,而另一个人则看到6 PM。

Instant instant = zdt.toInstant() ;

instant.toString():2020-01-23T21:00:00Z

您问过“来自世界各地的人们,有些人的夏令时时间不同”。您可以轻松地将时刻调整到其他时区。也许东京的某人想在他们的时区中看到相同的时刻,比UTC早几个小时,而不要落后几个小时。

ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdtTokyo = zdt.withZoneSameInstant( zTokyo ) ; 

或者:

ZonedDateTime zdtTokyo = instant.atZone( z ) ;

zdtTokyo.toString():2020-01-24T06:00 + 09:00 [亚洲/东京]

请注意日期是如何从23号跳到24号以及日期中的时间跳的。同样,同一时刻,不同的时钟时间。

请参阅此code run live at IdeOne.com


Table of all date-time types in Java, both modern and legacy


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容打下了基础。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:0)

问题,我想是你在getSomeDate()方法中只为SimpleDateFormat设置一次TimeZone。尝试为SimpleDateFormat的所有实例执行此操作。