2013-10-15 41 views
0

作为完全混淆什么用java时间会在,为什么有数以千计的与此相关的帖子我总算店时间UTC使用jodaTime的:转换时间回到指定的TimeZone

Calendar cal = new GregorianCalendar(); 

cal.setTimeInMillis(DateTimeZone.getDefault().convertLocalToUTC(
          cal.getTimeInMillis(), false)); 

由于我正在使用hibernate(并且不愿意使用适配器来为JodaTime正确使用版本4)我只使用此jodaTime方法将jdk时间转换为utc。这似乎产生了预期的结果,当地时间(当前伦敦GMT + 1)通过从当地时间减去1转换为UTC。

到目前为止这么好。然后,每当我检索特定时区的时间时,我都会得到不正确的偏移量-2,它应该是-3,包括DST。

Calendar cal = new GregorianCalendar();

  System.out.println("Local London Hours: "+cal.get(Calendar.HOUR_OF_DAY)); 
      System.out.println("Local London Milliseconds: "+cal.getTimeInMillis()); 

      cal.setTimeInMillis(DateTimeZone.getDefault().convertLocalToUTC(
        cal.getTimeInMillis(), false)); 

      System.out.println("UTC Hours: "+cal.get(Calendar.HOUR_OF_DAY)); 
      System.out.println("UTC Milliseconds: "+cal.getTimeInMillis()); 

      // Time for specific time zone 
      cal.setTimeZone(TimeZone.getTimeZone("Europe/Vilnius")); 


      System.out.println("Vilnius Hours: "+cal.get(Calendar.HOUR_OF_DAY)); 
      System.out.println("Vilnius Milliseconds: "+cal.getTimeInMillis()); 

      // is this time in DST? - Yes 
      System.out.println("Vilnius time is in DST: "+TimeZone.getTimeZone("Europe/Vilnius").inDaylightTime(cal.getTime())); 

http://www.timeanddate.com/worldclock/city.html?n=660时区的详细信息为特定时区

输出:

本地伦敦时间:21

本地伦敦毫秒:1381869901339

UTC时间:20

UTC毫秒:1381866301339

维尔纽斯时间:22 // 这应该是23(根据链路)

维尔纽斯毫秒:1381866301339

维尔纽斯时间是在DST:真// 没有,这是不是因为时间值不是23

回答

1

使用

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"); 

得到伦敦时间。

你应该能够将其与更改为UTC:

cal.setTimeZone(TimeZone.getTimeZone("UTC")); 

但是,有关于Calendar类一件有趣的事情。在更改时区之前和之后,如果您从中获得一些价值,则它效果最佳。因此,添加一行,

cal.get(Calendar.HOUR_OF_DAY); 

这将导致Calendar对象调整其内部的所有领域。

问题是它存储时间以毫秒为单位,它存储小时,日期和分钟以及其他字段中的所有内容。如果设置小时,则不会更新毫秒时间,直到您阅读某个字段。如果你打算设置日期和时间以及所有事情,那么无需每次都重新计算,只需要让它们全部更改。

同样,如果您更改毫秒时间或时区,它不会重新计算小时和天,直到您阅读它们。 (请注意,如果您使用的是调试器,这将使您感到困惑,因为调试器通常会调用其中一个get()以在调试控制台中显示值,这将修复Calendar对象,您将不会拥有如果你把它放在正确的地方,它可以工作。如果你把它放在正确的地方,它可以工作。它永远不会伤害。

注意

如果您使用JDBC存储日历作为数据库中的时间戳,它将存储毫秒的时间(或者我们可以认为这样的说法)。

然后,当JDBC读取毫秒时间时,创建一个Calendar对象并将其返回给您。创建的Calendar中包含默认的TimeZone

就像您将伦敦时间转换为UTC一样处理此事。

cal.get(Calendar.HOUR_OF_DAY); // funky Calendar magic to make sure it works 
cal.setTimeZone(TimeZone.getTimeZone("UTC")); 

这一切确实是更改存储TimeZone,这样,当像get(Calendar.HOUR_OF_DAY)执行下一个代码,将其转换存储的毫秒值的天(即UTC)的正确时区的时间。

+0

我认为它相当于新的GregorianCalendar(),因为服务器在伦敦? – Aubergine

+0

它应该是,但使用'日历'类似于黑魔法。你必须让这些咒语恰到好处地发挥作用。 –

+0

我跟着你更新你的答案,我想这条线解决了我的问题cal.setTimeZone(TimeZone.getTimeZone(“UTC”));我将检查它是否将值正确保存到数据库中(因为jodaTime方法似乎做得很好,但是破坏了其他所有内容)。即将接受。 – Aubergine