简体   繁体   中英

Java Convert TimeZone

I have seen several questions like this but I can't quite get the conversion right. I want to convert a date like the following

20121116203036Z

to

2012-11-16 15:30:36

I have the following code

    dateStringTime.set( year, mon-1 , day, hour, minute, second );

    Date date = dateStringTime.getTime();

    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    formatter.setTimeZone(TimeZone.getTimeZone("EST"));

    String output = formatter.format();
    return output;

which works but it gives me the below

2012-11-16 20:30:36

Any advice on how to get 15 instead of 20 ?

First, your code is not formatting 'date', try this:

  String output = formatter.format(date);

I also notice you are not showing us how you are creating dateStringTime which I assumed to be a Calendar . I noticed that the Calendar.getInstance() method also accepts a Locale which might affect the timezone.

My code:

    Calendar dateStringTime = Calendar.getInstance();

    //convert 20121116203036Z       
    int year = 2012;
    int mon = 11;
    int day = 16;
    int hour = 20;
    int minute = 30;
    int second = 36;

    dateStringTime.set( year, mon-1 , day, hour, minute, second );

    Date date = dateStringTime.getTime();

    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    formatter.setTimeZone(TimeZone.getTimeZone("EST"));

    String output = formatter.format(date);
    System.out.println(output);     

My output:

2012-11-16 21:30:36

You notice that the hour is 1 hour off? That is because I'm in the Central time zone and the JVM is taking that into account when I ask for 'EST'. It thinks that the original time is in the current timezone.

what happens when you comment out

        //formatter.setTimeZone(TimeZone.getTimeZone("EST"));

TimeZone. getDefault() will give the runtime timezone. If you will remove the getRawOffet value from date , you will have the UTC. one more step is to add/ remove the EST value from from UTC and is done the conversion

Your problem is that you're entering the date in the wrong timezone. When you do this

dateStringTime.set(year, month-1 , day, hour, minute, second);

you are actually entering the date using your default timezone, which is unlikely in your case to be UTC. Under the covers, the Java Date is represented as UTC, so it will translate the date/time to UTC rather than entering directly in UTC.

Basically, it's doing the following sequence of timezone translations: EST -> UTC -> EST

If you intend to specify a date/time using UTC, you should do this:

dateStringTime.setTimeZone(TimeZone.getTimeZone("UTC"));
dateStringTime.set(year, month-1 , day, hour, minute, second);

Then you'll only be going from UTC -> EST and you should get the proper output.

tl;dr

OffsetDateTime.parse(
    "20121116203036Z" , 
    DateTimeFormatter.ofPattern( "yyyyMMddHHmmssX" ) 
).toLocalDateTime()
 .toString()
 .replace( "T" , " " )

java.time

The java.time classes built into Java make this easy. Avoid the troublesome old date-time classes such as Date & DateFormat , now legacy.

String input = "20121116203036Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );

odt.toString(): 2012-11-16T20:30:36Z

To get your output you could define a custom DateTimeFormatter . A lazier way is to convert to a LocalDateTime just to lose the Z on the end, which indicates the offset-from-UTC ( Z is short for Zulu and means UTC). Then use toString to generate a string in ISO 8601 format except replace the T in the middle with a SPACE.

String output = odt.toLocalDateTime().toString().replace( "T" , " " );

2012-11-16 20:30:36

See live code in IdeOne.com .

ISO 8601

I suggest rather than using your format for such date-time values, instead use ISO 8601 standard formats. The usual format for such a value is 2016-11-16T02:45:02Z . Note the T in the middle separating year-month-day from hour-minute-second. Alternatively, the standard allows minimizing the use of separators, considered the “basic” version: 20161116T024502Z but retains the T in the middle.

The java.time classes can parse and generate the expanded versions but not the basic version.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date , .Calendar , & java.text.SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to java.time.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use… ).

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM