在不改变Java时间的情况下更改时区

13 java timezone datetime calendar

我从没有timzone信息的SOAP Web服务接收日期时间.因此,Axis解串器采用UTC.但是,日期时间确实在悉尼时间.我通过减去时区偏移来解决问题:

Calendar trade_date = trade.getTradeDateTime();
TimeZone est_tz = TimeZone.getTimeZone("Australia/Sydney");
long millis = trade_date.getTimeInMillis() - est_tz.getRawOffset();
trade_date.setTimeZone( est_tz );
trade_date.setTimeInMillis( millis );
Run Code Online (Sandbox Code Playgroud)

但是,我不确定此解决方案是否也考虑了夏令时.我认为应该,因为所有操作都是在UTC时间.有任何操纵Java时间的经验吗?关于如何解决这个问题的更好的想法?

Pau*_*and 19

我怜悯那些必须在Java做日期的傻瓜.

在夏令时过渡期间,你所做的几乎肯定会出错.最好的方法是创建一个新的Calendar对象,在其上设置Timezone,然后单独设置所有字段,如年,月,日,小时,分钟,秒,从Date对象获取值.

编辑:
为了让每个人都开心,你应该这样做:

Calendar utcTime = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar sydneyTime = Calendar.getInstance(TimeZone.getTimeZone("Australia/Sydney");
utcTime.setTime(trade_date);
for (int i = 0; i < Calendar.FIELD_COUNT; i++) {
  sydneyTime.set(i, utcTime.get(i));
}
Run Code Online (Sandbox Code Playgroud)

那么您将不会使用任何已弃用的方法.

  • @Alexander Pogrebnyak:我已经更新了答案,这样用户就不会陷入黑暗面;-) (2认同)

小智 5

我要感谢这个人的回应6.这对我来说是一个很好的开始,也是我没有考虑的方法.将它带到生产代码级别需要一些额外的步骤.特别要注意DST_OFFSET和ZONE_OFFSET所需的步骤.我想分享我想出的解决方案.

这将从输入Calendar对象获取时间,将其复制到输出时间,将新时区设置为输出.从数据库中抽取时间并设置时区而不更改时间时使用此方法.

public static Calendar setNewTimeZoneCopyOldTime( Calendar inputTime, 
        TimeZone timeZone ) {
    if( (inputTime == null) || (timeZone == null) ) { return( null ); }

    Calendar outputTime = Calendar.getInstance( timeZone );
    for( int i = 0; i < Calendar.FIELD_COUNT; i++ ) {
        if( (i != Calendar.ZONE_OFFSET) && (i != Calendar.DST_OFFSET) ) { 
            outputTime.set(i, inputTime.get(i));
        }
    }

    return( (Calendar) outputTime.clone() );
}
Run Code Online (Sandbox Code Playgroud)


小智 -1

我决定使用正确的时区集重新解析收到的日期时间字符串。这还应该考虑夏令时:

public class DateTest {

    private static SimpleDateFormat soapdatetime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

    /**
     * @param args
     */
    public static void main(String[] args) {
        TimeZone oztz = TimeZone.getTimeZone("Australia/Sydney");
        TimeZone gmtz = TimeZone.getTimeZone("GMT");
        Calendar datetime = Calendar.getInstance( gmtz );

        soapdatetime.setTimeZone( gmtz );
        String soap_datetime = soapdatetime.format( datetime.getTime() );
        System.out.println( soap_datetime );

        soapdatetime.setTimeZone( oztz );
        datetime.setTimeZone( oztz );
        try {
            datetime.setTime(
                    soapdatetime.parse( soap_datetime )
            );
        } catch (ParseException e) {
            e.printStackTrace();
        }

        soapdatetime.setTimeZone( gmtz );
        soap_datetime = soapdatetime.format( datetime.getTime() );
        System.out.println( soap_datetime );
    }
}
Run Code Online (Sandbox Code Playgroud)