我需要在项目中从一个时区转换为另一个时区。
我可以从当前时区转换为另一个时区,但不能从另一个时区转换为另一个时区。
例如,我在印度,并且能够使用Date d=new Date();将其分配给日历对象并设置时区,将其从印度转换为美国。
Date d=new Date()
但是,我不能从其他时区到另一个时区执行此操作。例如,我在印度,但是在将时区从美国转换为英国时遇到了麻烦。
tl; dr
ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" )) // Current moment in a particular time zone. .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" )) // Same moment adjusted into another time zone.
细节
java.util.Date类未分配时区†,但是其toString实现令人困惑地应用了JVM的当前默认时区。
java.util.Date
避免使用java.util.Date和.Calendar
这是避免与Java捆绑在一起的臭名昭著的java.util.Date,.Calendar和SimpleDateFormat类的众多原因之一。避免他们。而是使用以下任一方法:
java.time
Java 8和更高版本具有内置的java.time软件包。该软件包的灵感来自Joda-Time。尽管它们有一些相似之处和类名,但它们是不同的。每个都有其他不足的特征。一个显着的区别是java.time避免使用构造函数,而是使用静态实例化方法。这两个框架都由同一个人Stephen Colbourne领导。
在ThreeTen-Backport项目中,许多java.time功能都已反向移植到Java 6和7 。在ThreeTenABP项目中进一步适用于Android 。
就本课题而言,它们以相同的方式工作。指定一个时区,并调用一个now方法以获取当前时刻,然后基于旧的不可变实例创建一个新实例以适应时区。
请注意两个不同的时区类别。一个是命名时区,其中包括夏令时的所有规则和其他此类异常以及与UTC的偏移量,而另一个仅是偏移量。
ZoneId zoneMontréal = ZoneId.of("America/Montreal"); ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal ); ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo ); ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );
Joda-Time
以下是Joda-Time 2.3中的一些示例代码。在StackOveflow中搜索更多示例和更多讨论。
DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" ); DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" ); DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" ); DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone. DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata ); DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork ); DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC ); // Built-in constant for UTC.
我们在宇宙的时间轴上有四个相同时刻的表示。
†实际上,java.util.Date该类确实在其源代码中隐藏了一个时区。但出于大多数实际目的,该班级忽略了该时区。因此,简而言之,通常说juDate没有分配时区。令人困惑?是。避免使用juDate造成混乱,并使用Joda-Time和/或java.time。