时区转换
我需要在我的项目中从一个时区转换到另一个时区。
我能够从当前的时区转换到另一个时区,而不是从不同的时区转换到另一个时区。
例如,我在印度,我可以使用Date d=new Date();
从印度转换到美国Date d=new Date();
并将其分配给日历对象并设置时区。
但是,我不能从不同的时区到另一个时区。 例如,我在印度,但是我很难把时区从美国转换到英国。
一些例子
转换时区之间的时间
转换时区之间的时间
import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; public class TimeZoneExample { public static void main(String[] args) { // Create a calendar object and set it time based on the local // time zone Calendar localTime = Calendar.getInstance(); localTime.set(Calendar.HOUR, 17); localTime.set(Calendar.MINUTE, 15); localTime.set(Calendar.SECOND, 20); int hour = localTime.get(Calendar.HOUR); int minute = localTime.get(Calendar.MINUTE); int second = localTime.get(Calendar.SECOND); // Print the local time System.out.printf("Local time : %02d:%02d:%02d\n", hour, minute, second); // Create a calendar object for representing a Germany time zone. Then we // wet the time of the calendar with the value of the local time Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin")); germanyTime.setTimeInMillis(localTime.getTimeInMillis()); hour = germanyTime.get(Calendar.HOUR); minute = germanyTime.get(Calendar.MINUTE); second = germanyTime.get(Calendar.SECOND); // Print the local time in Germany time zone System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second); } }
java.util.Date类没有分配时区,但是它的实现混淆了JVM的当前默认时区。
避免java.util.Date&.Calendar
这是避免与Java捆绑在一起的令人讨厌的java.util.Date,.Calendar和SimpleDateFormat类的众多原因之一。 避免他们。 而是使用:
- Java 8中内置的java.time包 ,受到Joda-Time的启发。
- 乔达时间
java.time
Java 8和更高版本具有内置的java.time包 。 这个包是受Joda-Time的启发。 虽然他们有一些相似之处和阶级名称,但他们是不同的; 每个都有其他缺乏的function。 一个明显的区别是java.time避免了构造函数,而是使用静态实例化方法。 这两个框架都是由同一个人Stephen Colbourne领导的。
大部分的java.timefunction已被移植到ThreeTen-Backport项目中的Java 6和7。 在ThreeTenABP项目中进一步适应Android。
在这个问题的情况下,他们以同样的方式工作。 指定一个时区,然后调用now
方法获取当前时刻,然后基于旧的不可变实例创build一个新实例,以调整时区。
请注意两个不同的时区类。 一个是命名时区,其中包括夏令时和其他此类exception的所有规则,另加一个与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 2.3中的一些示例代码。 searchStackOveflow了解更多的例子和讨论。
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
类的源代码中隐藏了一个时区。 但是class级在最实际的用途上忽略了这个时区。 所以,作为速记,通常说juDate没有分配时区。 混乱? 是。 避免使用juDate,并使用Joda-Time和/或java.time。
Date date = new Date(); String formatPattern = ....; SimpleDateFormat sdf = new SimpleDateFormat(formatPattern); TimeZone T1; TimeZone T2; // set the Calendar of sdf to timezone T1 sdf.setTimeZone(T1); System.out.println(sdf.format(date)); // set the Calendar of sdf to timezone T2 sdf.setTimeZone(T2); System.out.println(sdf.format(date)); // Use the 'calOfT2' instance-methods to get specific info // about the time-of-day for date 'date' in timezone T2. Calendar calOfT2 = sdf.getCalendar();
通过适当设置Calendar
对象的时区,可以完全避免“默认”时区。 不过,我个人build议你使用Joda Time作为Java中date和时间操作的一个非常优越的API。 除此之外,乔达的时区转换非常简单。
目前还不清楚你现在的代码是什么样子的,为什么你只能通过默认的时区进行转换,但是在Joda Time中,你只需要在创build(比如说)一个DateTime
对象时明确指定时区,然后使用withZone(DateTimeZone zone)
。
如果您可以告诉我们更多关于如何获取input数据的信息,我们可以举一个更完整的例子。
您可以使用下面的代码片段
String dateString = "14 Jul 2014 00:11:04 CEST"; date = formatter.parse(dateString); System.out.println(formatter.format(date)); // Set the formatter to use a different timezone - Indochina Time formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok")); System.out.println("ICT time : "+formatter.format(date));
你可以这样做,以获得在另一个时区的当前时间
Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan")); japanCal.setTimeInMillis(local.getTimeInMillis());
取决于“转换”的真正含义。
它可能就像在FORMATTER中设置时区一样简单,而且不会与日历混合在一起。
Calendar cal = Calendar.getInstance(); TimeZone tzUTC = TimeZone.getTimeZone( "UTC" ); TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" ); DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm az" ); dtfmt.setTimeZone( tzUTC ); System.out.println( "UTC: " + dtfmt.format( cal.getTime() )); dtfmt.setTimeZone( tzPST ); System.out.println( "PST: " + dtfmt.format( cal.getTime() ));
如果你不想使用乔达,这是一个确定的方式使用内置的库。
首先我build议你强制你的JVM默认为一个时区。 这解决了当您将JVM从一台机器移动到另一台机器时可能遇到的问题,这些机器设置为不同的时区,但源数据始终是特定的时区。 例如,假设您的数据始终是PDT / PST时区,但您在设置为UTC时区的框上运行。
以下代码片段在我的JVM中设置了默认的时区:
//You can either pass the JVM a parameter that //enforces a TZ: java -Duser.timezone=UTC or you can do it //programatically like this TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone.setDefault(tz);
现在让我们说你的源date是作为PDT / PST进来,但你需要将其转换为UTC。 这些步骤是:
DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC")); String dateStrInPDT = "2016-05-19 10:00:00"; Date dateInPDT = dateFormat.parse(dateStrInPDT); String dateInUtc = dateFormatUtc.format(dateInPDT); System.out.println("Date In UTC is " + dateInUtc);
输出将是:
Date In UTC is 2016-05-19 17:00:00
你可以使用java.time.ZoneDateTime#ofInstant()
方法:
import java.time.*; public class TimeZonesConversion { static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) { return ZonedDateTime.ofInstant( time.toInstant(), newTimeZone); }; public static void main(String... args) { ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone()); System.out.println("MST(" + mstTime + ") = " + localTime); } }
这不是答案,但可以帮助某人尝试生成具有相同时区的date,并应用另一个时区的偏移量。 当您的应用程序服务器在一个时区内运行,而您的数据库在另一个时区内时,这非常有用
public static Date toGreekTimezone (Date date) { ZoneId greek = ZoneId.of(EUROPE_ATHENS); ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek); ZoneId def = ZoneId.systemDefault(); ZonedDateTime defDate = greekDate.withZoneSameLocal(def); return Date.from(defDate.toInstant()); }
public static void convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone) { long milliseconds = date.getTime(); milliseconds += (fromTimeZone.getRawOffset() * -1); if (fromTimeZone.inDaylightTime(date)) { milliseconds += (fromTimeZone.getDSTSavings() * -1); } milliseconds += toTimeZone.getRawOffset(); if (toTimeZone.inDaylightTime(date)) { milliseconds += toTimeZone.getDSTSavings(); } date.setTime(milliseconds); }