Convert unix timestamp between different timezones and different DST in Java

半腔热情 提交于 2019-12-20 04:13:08

问题


PROBLEM SOLVED External device was computing and sending non-standard 2 hours shifted timestamp, which hugely confused me and started this thread. TIMESTAMP BY ITSELF IS NOT AFFECTED BY TIMEZONES , timezones apply only when converting in/from human readable forms.


I have timestamp (seconds from unix epoch) in UTC timezone - no DST (daylight saving time).

I want timestamp (seconds from unix epoch) in "Europe/Prague" timezone, that uses DST.

I used to think that unix timestamp is unbound by timezones, that timezones affect only process of converting timestamp to human readable formats. But it doesn't look like that. And the more I am trying to convert it (using Calendar and TimeZone classes), the more confused and lost I am getting.

this code DOES NOT work as expected:

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

回答1:


There is not a way to "convert" a timestamp, it is always the number of milliseconds from the epoch.

You can use a DateFormat to format the timestamp into a format with a time zone applied, or use a Calendar to look at the hours, minutes, and seconds with a time zone applied.

getTimeInMillis() gets the timestamp back just the same as you put it in, the number of milliseconds from the epoch: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#getTimeInMillis%28%29




回答2:


Here is a sample code to convert epoch between timezones.

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();
}

Output:

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



回答3:


You can easily convert between two timezone like this:

1.Suppose this is a date and time in the EST timezone

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 and assumes it represents a date and time in the EST timezone

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

3.Formats the date in the CET timezone

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



回答4:


It behaves as I would expect

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()));
}

prints

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


来源:https://stackoverflow.com/questions/16148198/convert-unix-timestamp-between-different-timezones-and-different-dst-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!