在Java中转换不同时区和不同DST之间的unix时间戳

时间:2013-04-22 13:20:48

标签: java timezone dst java.util.date

问题已解决外部设备正在计算并发送非标准的2小时移动时间戳,这让我非常困惑并启动了此线程。 TIMESTAMP自身不受时区的影响,时区只适用于人类可读形式的转换。


我有UTC时区的时间戳(来自unix纪元的秒数​​) - 没有夏令时(夏令时)。

我想要使用DST的“欧洲/布拉格”时区的时间戳(来自unix纪元的秒数​​)。

我以前认为unix时间戳不受时区的限制,时区只影响将时间戳转换为人类可读格式的过程。但它看起来并不像那样。我试图转换它的次数越多(使用Calendar和TimeZone类),我就会越困惑和迷失。

此代码无法按预期工作:

Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTimeInMillis(ts*1000);
cal.setTimeZone(TimeZone.getTimeZone("Europe/Prague"));
return cal.getTimeInMillis()/1000;

4 个答案:

答案 0 :(得分:5)

没有办法“转换”时间戳,它总是从纪元开始的毫秒数。

您可以使用DateFormat将时间戳格式化为应用了时区的格式,或使用日历查看应用了时区的小时,分​​钟和秒。

getTimeInMillis()获取的时间戳与您输入的时间戳相同,即epoch的毫秒数: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#getTimeInMillis%28%29

答案 1 :(得分:2)

以下是在时区之间转换纪元的示例代码。

public static long convertTimeZone(long lngDate, String fromTimeZone,
        String toTimeZone) {        
    Calendar fromTime = Calendar.getInstance();
    fromTime.setTimeZone(TimeZone.getTimeZone(fromTimeZone));
    fromTime.setTimeInMillis(lngDate);
    Calendar toTime = new GregorianCalendar(
            TimeZone.getTimeZone(toTimeZone));
    toTime.set(Calendar.DATE, fromTime.get(Calendar.DATE));
    toTime.set(Calendar.MONTH, fromTime.get(Calendar.MONTH));
    toTime.set(Calendar.YEAR, fromTime.get(Calendar.YEAR));
    toTime.set(Calendar.HOUR_OF_DAY, fromTime.get(Calendar.HOUR_OF_DAY));
    toTime.set(Calendar.MINUTE, fromTime.get(Calendar.MINUTE));
    toTime.set(Calendar.SECOND, fromTime.get(Calendar.SECOND));
    toTime.set(Calendar.MILLISECOND, fromTime.get(Calendar.MILLISECOND));
    LOG.debug("Converted " + fromTime.getTimeInMillis() + " to "
            + toTime.getTimeInMillis());
    SimpleDateFormat sdf = new SimpleDateFormat(
            "dd-MMM-yyyy HH:mm:ss.SSS z");      
    sdf.setTimeZone(TimeZone.getTimeZone(fromTimeZone));        
    SimpleDateFormat sdf1 = new SimpleDateFormat(
            "dd-MMM-yyyy HH:mm:ss.SSS z");      
    sdf1.setTimeZone(TimeZone.getTimeZone(toTimeZone));
    LOG.debug("Converted " + sdf.format(fromTime.getTime()) + " to " + sdf1.format(toTime.getTime()));
    return toTime.getTimeInMillis();
}

输出:

System.out.println(convertTimeZone(new Date().getTime(),"America/New_York","Asia/Singapore"));
Converted 1384514879944 to 1384468079944
Converted 15-Nov-2013 06:27:59.944 EST to 15-Nov-2013 06:27:59.944 SGT

答案 2 :(得分:0)

您可以轻松地在两个时区之间进行转换:

1.假设这是EST时区的日期和时间

String value = "2006-11-28 09:45:12";  
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
df1.setTimeZone(TimeZone.getTimeZone("EST"));  

2.Parses the value并假设它代表EST时区的日期和时间

Date d = df1.parse(value);     
DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
df2.setTimeZone(TimeZone.getTimeZone("CET")); 

3.在CET时区中格式化日期

System.out.println(df2.format(d)); 

答案 3 :(得分:0)

它表现得像我期望的那样

public static void main(String... ignored) {
    long ts = System.currentTimeMillis() / 1000;
    Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
    printCalendar(cal);
    cal.setTimeInMillis(ts * 1000);
    printCalendar(cal);
    cal.setTimeZone(TimeZone.getTimeZone("Europe/Prague"));
    printCalendar(cal);
}

public static void printCalendar(Calendar calendar) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ZZZ");
    sdf.setTimeZone(calendar.getTimeZone());
    System.out.println(sdf.format(calendar.getTime()));
}

打印

2013/04/22 13:28:06.451 +0000
2013/04/22 13:28:06.000 +0000
2013/04/22 15:28:06.000 +0200