Java 转换为UTC考虑夏令时

Java 转换为UTC考虑夏令时,java,date,datetime,timezone,utc,Java,Date,Datetime,Timezone,Utc,我在时区中有一个日期,例如2014年4月17日09:03:01 GMT周四: sun.util.calendar.ZoneInfo[id=“欧洲/伦敦”,偏移量=0,DSTSAVAINGS=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,DStSaves=3600000,useDaylight=true,startYear=0,startMod

我在时区中有一个日期,例如2014年4月17日09:03:01 GMT周四:

sun.util.calendar.ZoneInfo[id=“欧洲/伦敦”,偏移量=0,DSTSAVAINGS=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,DStSaves=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=1,startDayOfWeek=1,startDayOfWeek=1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endDayOfWeek=1,endDayOfWeek=2]

每次尝试转换为UTC时,它都会返回2014年4月17日星期四10:03:01 GMT

这是没有意义的,因为相应的UTC时间实际上是2014年4月17日08:03:01 GMT周四,因为我所在时区的时间由于夏令时而增加了1小时

我用于转换的代码如下:

//timeZone - id="Europe/London"
public static Date timeZoneConvertDate(Date date, TimeZone timeZone) {
        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.setTimeZone(timeZone);
        sdf.applyPattern("dd-MM-yyyy HH:mm:ss");
        String newDate = sdf.format(date);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        try {
            Date nd = sdf.parse(newDate);
            return nd;
        } catch (ParseException e) {
            return null;
    }
}
有人能解释一下我做错了什么吗
日期
没有与之关联的时区,因此无法创建调整日期对象时区的方法。如果要保留TZ信息,或者最好查看,则需要使用
日历
对象

对输出的解释
Date
值没有时区信息;它只是从纪元开始的毫秒数。记住这一点,让我们看看您在做什么:

SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(timeZone);
sdf.applyPattern("dd-MM-yyyy HH:mm:ss");
String newDate = sdf.format(date);
这部分代码将创建一个格式化程序,用于打印伦敦时区中的日期。因此,在编写本文时,您将得到的结果约为:
17-04-2014 11:38:15
(假设您刚刚创建了日期对象)

在这里,您告诉日期分析器读取日期,就好像它是UTC日期一样。它使用该信息来知道从纪元到现在已经过去了多少毫秒。您返回的日期对象仍然没有与其关联的时区

UTC比英国夏令时晚一小时,因此它将创建一个日期对象,当在BST时区打印时,该对象将提前一小时显示。因此,当我打印
nd
,我得到:
2014年4月17日星期四12:38:15英国夏令时

java.util.date中没有时区 如上所述,java.util.Date没有时区组件。令人困惑的是,它的
toString
方法应用JVM的默认时区。要在另一个时区中显示,请使用SimpleDataFormat应用调整

更好的是,避免众所周知的麻烦的java.util.Date、.Calendar和SimpleDataFormat

乔达时间 在Joda Time中,DateTime对象确实包含指定的时区。如果不指定时区,JVM的默认时区将被指定

DateTimeZone timeZone = DateTimeZone.forID( "Europe/London" );
DateTime dateTime = new DateTime( 2014, 4, 17, 9, 3, 1, timeZone );
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
DateTime dateTimeIndia = dateTime.withZone( DateTimeZone.forID( "Asia/Kolkata" ) );
当运行时

dateTime:2014-04-17T09:03:01.000+01:00
日期时间UTC:2014-04-17T08:03:01.000Z
印度日期时间:2014-04-17T13:33:01.000+05:30(注意半小时的差异,+05:30)
您可以轻松地来回转换为java.util.Date

DateTime dateTime = new DateTime( myJUDate, timeZone );
……还有

Java.util.Date date = dateTime.toDate();

将一个对象转换为字符串,然后对其进行解析以将其转换回字符串,这不是一个好做法。我会使用joda时间库进行这种转换:@Duncan这是我的错误,我已经纠正了这个问题。你是否假设在代码开始时,日期值是2014年4月17日10:03:01 GMT周四?@DiogoPinheiro当我运行代码生成我的示例,时间是17-04-2014 11:38:15 BST/17-04-2014 10:38:15 GMT/1397731095000ms,从1970年1月1日开始。我如何获得正确的日期?我希望UTC比英国夏季时间晚一小时。我找不到任何解决方案。谢谢you@DiogoPinheiro正如我所说的,
日期
代表了生命中的一个瞬间时间,不带任何时区。如果要查看特定时区中的日期值(作为字符串),请使用
SimpleDateFormat
,就像方法的前四行一样。
Java.util.Date date = dateTime.toDate();