简体   繁体   中英

Java convert ISO 8601 string to Date ignoring offset

I have a string coming to me in the following format "yyyy-MM-dd'T'HH:mm:ssZ" ex: 2020-09-09T09:58:00+0000" offset is UTC.

I need the string to be converted to a Date object without the offset "+0000" being applied, but I keep getting a different time when running my code:

DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
Date date = isoFormat.parseDateTime("2020-09-09T09:58:00+0000").toDate();
// Wed Sep 09 05:58:00 EDT 2020

As you can see above the date has changed.

Instead, I would like to keep the same date and time like: Wed Sep 09 09:58:00, so I can convert this Date object to a String with "yyyy-MM-dd", "HH:mm:ss", and "yyyy-MM-dd'T'HH:mm:ss" format respectively.

I recommend you do it with the modern java.time date-time API and the corresponding formatting API (package, java.time.format ). Learn more about the modern date-time API from Trail: Date Time .

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // The given date-time string
        String strDateTime = "2020-09-09T09:58:00+0000";

        // Define the formatter
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ");

        // Parse the given date-time string into OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime, formatter);

        // Output OffsetDateTime in the default format
        System.out.println(odt);

        // Print OffsetDateTime using the defined formatter
        String formatted = formatter.format(odt);
        System.out.println(formatted);
    }
}

Output:

2020-09-09T09:58Z
2020-09-09T09:58:00+0000

Note: java.util.Date does not represent a Date/Time object. It simply represents the no. of milliseconds from the epoch of 1970-01-01T00:00:00Z . It does not have any time-zone or zone-offset information. When you print it, Java prints the string obtained by applying the time-zone of your JVM. I suggest you stop using java.util.Date and switch to the modern date-time API.

Using joda date-time API, you can do it as follows:

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

public class Main {
    public static void main(String[] args) {
        // The given date-time string
        String strDateTime = "2020-09-09T09:58:00+0000";

        // Define the formatter
        DateTimeFormatter isoFormat = ISODateTimeFormat.dateTimeParser();
        DateTime dateTime = isoFormat.parseDateTime("2020-09-09T09:58:00+0000");

        // Display DateTime in the default format
        System.out.println(dateTime);

        // Define formatter for ouput
        DateTimeFormatter outputFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC();

        // Display DateTime in the defined output format
        String formatted = outputFormat.print(dateTime);
        System.out.println(formatted);
    }
}

Output:

2020-09-09T10:58:00.000+01:00
2020-09-09T09:58:00+0000

The first and most important part of the answer is: don't convert to an old-fashioned Date . Either stick to Joda-Time or migrate to java.time, the modern Java date and time API, as already covered in the good answer by Arvind Kumar Avinash.

Since you are already using Joda-Time, I am showing you a Joda-Time solution. The trick for persuading the formatter into keeping the time and offset from the string parsed is withOffsetParsed() .

    DateTimeFormatter isoFormat
            = ISODateTimeFormat.dateTimeParser().withOffsetParsed();
    String incomingString = "2020-09-09T09:58:00+0000";
    DateTime dateTime = isoFormat.parseDateTime(incomingString);

However! If I have guessed correctly that you want to store date and time in UTC (a recommended practice), better than withOffsetParsed() is to specify UTC on the parser:

    DateTimeFormatter isoFormat
            = ISODateTimeFormat.dateTimeParser().withZoneUTC();

Now you will also get the correct time if one day a string with a non-zero UTC offset comes in.

In any case we may now format your obtained DateTime into the strings you requested.

    String dateString = dateTime.toString(ISODateTimeFormat.date());
    System.out.println(dateString);
    
    String timeString = dateTime.toString(ISODateTimeFormat.hourMinuteSecond());
    System.out.println(timeString);
    
    String dateTimeString = dateTime.toString(ISODateTimeFormat.dateHourMinuteSecond());
    System.out.println(dateTimeString);

Output:

 2020-09-09 09:58:00 2020-09-09T09:58:00

What was wrong with using Date ? First, the Date class is poorly designed and long outdated. Second, a Date was just a point in time, it didn't have a concept of date and time of day (they tried building that into it in Java 1.0, but gave up and deprecated it in Java 1.1 in 1997). So a Date cannot hold the date and time of day in UTC for you.

What happened in your code was that you got a Date representing the correct point in time. Only when you printed that Date you were implicitly invoking its toString method. Date.toString() confusingly grabs the JVM's time zone setting (in your case apparently North American Eastern Time) and uses it for rendering the string to be returned. So in your case the point in time was rendered as Wed Sep 09 05:58:00 EDT 2020 .

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