1

问题已解决外部设备正在计算和发送非标准的 2 小时偏移时间戳,这让我非常困惑并开始了这个线程。TIMESTAMP 本身不受 TIMEZONES的影响,时区仅在转换为/从人类可读形式转换时适用。


我在 UTC 时区有时间戳(从 unix 纪元开始的秒数) - 没有 DST(夏令时)。

我想要使​​用 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

4 回答 4

5

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

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

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

于 2013-04-22T13:32:45.047 回答
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
于 2013-11-15T11:30:06.043 回答
1

它的行为如我所料

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
于 2013-04-22T13:29:01.460 回答
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.解析该值并假设它代表 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)); 
于 2013-04-22T13:27:12.043 回答