I have a date, for example Thu April 17 09:03:01 GMT 2014 in the timezone:

sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]

and everytime a try to convert to UTC it returns Thu April 17 10:03:01 GMT 2014

This does not make sense because the corresponding UTC time is actually Thu April 17 08:03:01 GMT 2014 since that the in my timezone time is added 1hour due to daylight savings.

The code I use to convert is this:

//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;
    }
}

Could someone explain what I'm doing wrong?

有帮助吗?

解决方案

tl;dr

A Date has no timezone associated with it, so you cannot create a method that adjusts the timezone of a date object. You need to work with Calendar objects if you want to retain TZ information or, preferably, take a look at Joda-Time.

Explanation of Your Output

A Date value has no timezone information; it's merely the number of milliseconds since the epoch. With that in mind, let's see what you're doing:

SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(timeZone);
sdf.applyPattern("dd-MM-yyyy HH:mm:ss");
String newDate = sdf.format(date);

This part of your code creates a formatter that will print the date in the London timezone. So the result you'll get at the time of writing is approximately: 17-04-2014 11:38:15 (assuming you just created your date object).

sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
  Date nd = sdf.parse(newDate);
  return nd;
} catch (ParseException e) {
   return null;
}

Here you tell the date parser to read the date as though it were a UTC date. It uses that information to know how many milliseconds since the epoch have passed. The date object you get back still has no timezone associated with it.

UTC is an hour behind British Summer Time, so it will create a date object that appears an hour ahead when printed in the BST timezone. So when I print nd, I get: Thu Apr 17 12:38:15 BST 2014.

其他提示

No Time Zone In java.util.Date

As the correct answer by Duncan said a java.util.Date has no time zone component. Confusingly its toString method applies the JVM's default time zone. To display in another time zone, use SimpleDateFormat to apply an adjustment.

Even better, avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat. Use either Joda-Time or the new java.time package in Java 8.

Joda-Time

In Joda-Time, a DateTime object truly does contain an assigned time zone. If you do not specify a time zone, the JVM's default time zone is assigned.

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" ) );

When run…

dateTime: 2014-04-17T09:03:01.000+01:00
dateTimeUtc: 2014-04-17T08:03:01.000Z
dateTimeIndia: 2014-04-17T13:33:01.000+05:30 (note the half-hour difference, +05:30)

You can easily convert back and forth to java.util.Date.

DateTime dateTime = new DateTime( myJUDate, timeZone );

…and…

Java.util.Date date = dateTime.toDate();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top