考虑夏令时,将本地时间转换为UTC时间,反之亦然

我知道如何将本地时间转换为UTC时间,反之亦然。 但是,在执行此操作时,我对夏令时(DST)处理非常困惑。

所以任何人都可以回答以下问题:
1.在时区之间转换时,java内部处理DST吗?
2.在时区之间转换时我需要做些什么?
3.更清楚地解释这个问题的任何好文章?

提前致谢。

您确定知道如何将日期转换为UTC并返回吗? 正确?
我很害怕,我对此表示怀疑。

  1. 是。
  2. 您不需要转换,只需要分配正确的TimeZone即可。
  3. 您需要什么文章? 好的,我正在研究这个问题,但现在让我在这里给出答案。

首先是第一件事。 您的程序应在内部以UTC TimeZone存储日期(或日历)。 好吧,事实上在GMT中,因为Java中没有闰秒,但那是另一回事。
你应该需要“转换”的唯一地方就是你要向用户显示时间。 这也涉及发送电子邮件。 在这两种情况下,您都需要格式化日期以获取其文本表示。 为此,您将使用DateFormat并分配正确的TimeZone:

  // that's for desktop application // for web application one needs to detect Locale Locale locale = Locale.getDefault(); // again, this one works for desktop application // for web application it is more complicated TimeZone currentTimeZone = TimeZone.getDefault(); // in fact I could skip this line and get just DateTime instance, // but I wanted to show how to do that correctly for // any time zone and locale DateFormat formatter = DateFormat.getDateTimeInstance( DateFormat.DEFAULT, DateFormat.DEFAULT, locale); formatter.setTimeZone(currentTimeZone); // Dates "conversion" Date currentDate = new Date(); long sixMonths = 180L * 24 * 3600 * 1000; Date inSixMonths = new Date(currentDate.getTime() + sixMonths); System.out.println(formatter.format(currentDate)); System.out.println(formatter.format(inSixMonths)); // for me it prints // 2011-05-14 16:11:29 // 2011-11-10 15:11:29 // now for "UTC" formatter.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println(formatter.format(currentDate)); System.out.println(formatter.format(inSixMonths)); // 2011-05-14 14:13:50 // 2011-11-10 14:13:50 

如您所见,Java关心处理DST。 您当然可以手动处理它,只需阅读TimeZone相关的JavaDoc 。

这是我找到的最佳解决方案。 我在这里复制它,但解决方案来自http://biese.wordpress.com/2014/02/28/the-easy-way-to-convert-local-time-to-utc-time/ 。

 package com.test.timezone; import java.util.TimeZone; public final class Utility { public static final TimeZone utcTZ = TimeZone.getTimeZone("UTC"); public static long toLocalTime(long time, TimeZone to) { return convertTime(time, utcTZ, to); } public static long toUTC(long time, TimeZone from) { return convertTime(time, from, utcTZ); } public static long convertTime(long time, TimeZone from, TimeZone to) { return time + getTimeZoneOffset(time, from, to); } private static long getTimeZoneOffset(long time, TimeZone from, TimeZone to) { int fromOffset = from.getOffset(time); int toOffset = to.getOffset(time); int diff = 0; if (fromOffset >= 0){ if (toOffset > 0){ toOffset = -1*toOffset; } else { toOffset = Math.abs(toOffset); } diff = (fromOffset+toOffset)*-1; } else { if (toOffset <= 0){ toOffset = -1*Math.abs(toOffset); } diff = (Math.abs(fromOffset)+toOffset); } return diff; } } package com.test.timezone; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; public class TestTimezone { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMM dd HH:mm:ss zzzz"); Calendar date1 = new GregorianCalendar(2014,0,15,10,0,0); System.out.println(sdf.format(date1.getTime())+"\n"); long utcTimeStamp = Utility.toUTC(date1.getTimeInMillis(), date1.getTimeZone()); Calendar utcCal = Calendar.getInstance(); utcCal.setTimeInMillis(utcTimeStamp); System.out.println("toUTC: "+sdf.format(utcCal.getTime())+"\n"); System.out.println("---------------------------------------"); Calendar date2 = new GregorianCalendar(2014,2,15,10,0,0); System.out.println(sdf.format(date2.getTime())+"\n"); utcTimeStamp = Utility.toUTC(date2.getTimeInMillis(), date2.getTimeZone()); utcCal.setTimeInMillis(utcTimeStamp); System.out.println("toUTC: "+sdf.format(utcCal.getTime())+"\n"); System.out.println("---------------------------------------"); Calendar date3 = new GregorianCalendar(2014,11,25,9,0,0); System.out.println(sdf.format(date3.getTime())+"\n"); long uTime = Utility.toUTC(date3.getTimeInMillis(), date3.getTimeZone()); System.out.println("utcTimeStamp: "+uTime+"\n"); long lTime = Utility.toLocalTime(uTime, TimeZone.getTimeZone("EST")); Calendar locCal = Calendar.getInstance(); locCal.setTimeInMillis(lTime); System.out.println("toLocal: "+sdf.format(locCal.getTime())+"\n"); System.out.println("---------------------------------------"); Calendar date4 = new GregorianCalendar(2014,6,4,9,0,0); System.out.println(sdf.format(date4.getTime())+"\n"); uTime = Utility.toUTC(date4.getTimeInMillis(), date4.getTimeZone()); System.out.println("utcTimeStamp: "+uTime+"\n"); lTime = Utility.toLocalTime(uTime, TimeZone.getTimeZone("EST")); locCal = Calendar.getInstance(); locCal.setTimeInMillis(lTime); System.out.println("toLocal: "+sdf.format(locCal.getTime())+"\n"); } } 

TALE答案中的代码可以简化:

 public final class Utility { public static long toLocalTime(long time, TimeZone to) { return time + to.getOffset(time); } public static long toUTC(long time, TimeZone from) { return time - from.getOffset(time); } }