我知道如何将本地时间转换为UTC时间,反之亦然。但是在执行此操作时,我对夏令时(DST)处理感到非常困惑。
所以任何人都可以回答以下问题:
1. 在时区之间转换时,java 是否在内部处理 DST?
2. 在时区之间转换时我需要做什么?
3. 有什么好文章可以更清楚地解释这一点吗?
提前谢谢。
您确定知道如何将日期转换为 UTC 并返回吗?正确?
恐怕,我对此表示怀疑。
- 是的。
- 您不需要转换,只需要分配正确的时区。
- 你需要一篇文章做什么?好的,我正在努力解决这个问题,但现在让我在这里给出一个答案。
首先是。程序应在内部以 UTC 时区存储日期(或日历)。好吧,事实上在格林威治标准时间,因为Java中没有闰秒,但那是另一回事了。
唯一需要"转换"的地方是要向用户显示时间的时间。这也与发送电子邮件有关。在这两种情况下,您都需要格式化日期以获取其文本表示形式。为此,您将使用DateFormat
并分配正确的时区:
// 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。您当然可以手动处理它,只需阅读与时区相关的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);
}
}