Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中更改时区而不更改时间_Java_Datetime_Calendar_Timezone - Fatal编程技术网

在Java中更改时区而不更改时间

在Java中更改时区而不更改时间,java,datetime,calendar,timezone,Java,Datetime,Calendar,Timezone,我从一个SOAP Web服务接收到一个没有timzone信息的datetime。因此,Axis反序列化器采用UTC。然而,日期时间实际上是在悉尼时间。我通过减去时区偏移量解决了这个问题: Calendar trade_date = trade.getTradeDateTime(); TimeZone est_tz = TimeZone.getTimeZone("Australia/Sydney"); long millis = trade_date.getTimeInMillis() - est

我从一个SOAP Web服务接收到一个没有timzone信息的datetime。因此,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 );

然而,我不确定这个解决方案是否也考虑了夏令时。我认为应该这样,因为所有操作都是在UTC时间进行的。有在Java中操作时间的经验吗?如何解决这个问题有更好的办法吗?

我可怜那个用Java进行约会的傻瓜

在夏令时转换期间,您所做的几乎肯定会出错。最好的方法可能是创建一个新的日历对象,在其上设置时区,然后分别设置所有字段,例如年、月、日、小时、分钟、秒,从日期对象获取值

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

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));
}
日历utcTime=Calendar.getInstance(TimeZone.getTimeZone(“UTC”); Calendar sydneyTime=Calendar.getInstance(TimeZone.getTimeZone(“澳大利亚/悉尼”); utcTime.setTime(交易日); 对于(int i=0;i 这样就不会使用任何不推荐使用的方法

但是,我不确定这个解决方案 还将夏令时纳入 我想应该是的,因为 所有操作均在UTC时间进行

是的,您应该考虑夏令时,因为它会影响到UTC的偏移量

有没有在Java中操作时间的经验?关于如何解决这个问题的更好的想法

是一个更好的时间API。以下代码片段可能会有所帮助:

DateTimeZone zone; // TODO : get zone
DateTime fixedTimestamp = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, zone);
JordaMyType是不可变的,这也是一个好处。

< P>我决定重新解析用正确的时区集合接收的DATESTEN字符串。
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 );
    }
}

我通常是这样做的

Calendar trade_date_utc = trade.getTradeDateTime();
TimeZone est_tz = TimeZone.getTimeZone("Australia/Sydney");
Calendar trade_date = Calendar.GetInstance(est_tz);
trade_date.setTimeInMillis( millis );

我想感谢这个人6。这对我来说是一个很好的开始,也是一个我没有考虑的方法。需要一些附加的步骤来把它带到生产代码级别。特别是观察DSTHOBLASH和ZON-OffOffice所需的步骤。我想分享我想出的解决方案。

这将从输入日历对象获取时间,将其复制到输出时间,将新时区设置为输出。这用于从数据库中提取时间并在不更改时间的情况下设置时区

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() );
}
公共静态日历设置NewTimeZoneCopyOldTime(日历输入时间,
时区(时区){
如果((inputTime==null)| |(时区==null)){return(null);}
Calendar outputTime=Calendar.getInstance(时区);
对于(int i=0;i
您是否从混乱的Web服务中获得了ISO 8601样式的字符串?如果是这样,Joda Time 2.3库使这变得非常简单

如果您得到的是没有任何时区偏移的ISO 8601字符串,则将时区对象传递给DateTime构造函数

DateTimeZone timeZone = DateTimeZone.forID( "Australia/Sydney" );
String input = "2014-01-02T03:00:00"; // Note the lack of time zone offset at end.
DateTime dateTime = new DateTime( input, timeZone );
转储到控制台

System.out.println( "dateTime: " + dateTime );
当运行时

dateTime:2014-01-02T03:00:00.000+11:00

运行日历测试
2016-06-30 19:09:16.522+0300
1467302956522
2016-06-30 19:09:16.522+0100
146730156522

测试运行:1,失败:0,错误:0,跳过:0,运行时间:0.137秒;@Alexander Pogrebnyak:我已经更新了答案,这样用户就不会被带到黑暗面;-)我总是,永远,并且只通过使用唯一固定的单位来操纵日期(用任何语言)。这个单位是秒(或毫秒)。有59秒或61秒的分钟,也有23小时或25小时的天。有60*60+/-1秒的小时,等等。我的所有日期都存储为(毫秒)秒,从历元开始。这就是它们在数据库中的方式,这就是它们的排序方式。我进行时区/yyyy-mm-dd转换的唯一时间是当需要向用户显示时(或者当使用不理解日期以秒表示的坏API时)。@wizardofods。这是一个合理的建议,但OP清楚地表明,他从web服务(可能是第三方)接收时间戳,并使用第三方库处理该请求。显然,有些事情是他无法直接控制的,使用java.util.Calendar从时区转换到时区肯定不是一件简单的事情。谢谢您的评论。我使用Axis从WSDL文件生成Web服务存根。我正在使用生成的类连接到第三方web服务。实际上,我认为他们应该用时区信息或UTC传输日期时间字段,这正是Axis所期望的。但这不是我的选择。谢谢你链接到JodaTime。但是,我不会为该项目引入新的第三方库。但是我会考虑NEX时间。JoDaTimes非常值得添加第三方库。久经考验的。众所周知,java.util.Date和Calendar类非常麻烦。
 @Test
 public void tzTest() {
     SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
     TimeZone tz1 = TimeZone.getTimeZone("Europe/Moscow");
     Calendar cal1 = Calendar.getInstance(tz1);
     long l1 = cal1.getTimeInMillis();
     df.setTimeZone(tz1);
     System.out.println(df.format(cal1.getTime()));
     System.out.println(l1);
     TimeZone tz2 = TimeZone.getTimeZone("Africa/Douala");
     Calendar cal2 = Calendar.getInstance(tz2);
     long l2 = l1 + tz1.getRawOffset() - tz2.getRawOffset();
     cal2.setTimeInMillis(l2);
     df.setTimeZone(tz2);
     System.out.println(df.format(cal2.getTime()));
     System.out.println(l2);
     assertNotEquals(l2, l1);
 }