Java Time API converts ISO 8601 to ZonedDateTime

I'm having a hard time converting an ISO 8601 formatted string to java.time.LocalDateTime , which is in UTC.

More specifically, I'm trying to write the XMLAdapter , for which you can enter a variety of formats ISO 8601 data as a string (eg 2002-09-24

, 2011-03-22T13:30

, 2015-05-24T12:25:15Z

, 2015-07-28T11:11:15.321+05:30

), and which gives LocalDateTime UTC and vice versa.

The system stores all date and time information internally in UTC time. When a user requests a date or time, it is presented to the user based on its own ZoneId .

+3


source to share


3 answers


As the name suggests, LocalDateTime

contains date and time. For example, the first example of the date string you have in your question only contains date information, so you cannot parse it directly into LocalDateTime

. What you can do is first disassemble it in LocalDate

and set the time on that object by getting LocalDateTime

.

LocalDateTime localDateTime = LocalDate.parse("2002-09-24").atStartOfDay();

      



All Date and Time objects have a parse method, for example LocalDate

, which can accept a specific string format. These formats are ISO standard formats as specified in DateTimeFormatter

To format custom datetime strings to objects, Temporal

use DateTimeFormatter and provide your own template.

+1


source


TL; DR

Instant.parse( "2015-05-24T12:25:15Z" )
       .atZone( ZoneId.of( "America/Montreal" ) )

      

ZonedDateTime

vs LocalDateTime

Your question contradicts itself, with a title requesting ZonedDateTime

and a body requesting LocalDateTime

. These are two completely different beasts. One ( ZonedDateTime

) is a specific moment on the timeline, the other ( LocalDateTime

) is only a vague idea of โ€‹โ€‹possible moments, but not a specific moment.

For example, LocalDateTime

Christmas starting this year, 2017-12-25T00:00:00

but it doesn't matter until you apply the time zone as Santa delivers first to the Kiribati Islands at midnight (the first midnight on Earth), then to New Zealand at a later midnight, then at Australia at later midnight and so on, moving west towards consecutive midnight.

Also, you seem to be confusing the question of what the input is and what the result is.

Instant

To enter a type 2015-05-24T12:25:15Z

that represents a moment on the timeline in UTC (which Z

is short for Zulu

and stands for UTC). To represent this, use the class Instant

. The class Instant

represents a moment on the timeline in UTC with nanosecond resolution (up to nine (9) decimal places).

Instant instant = Instant.parse( "2015-05-24T12:25:15Z" );

      

Typically, you should work in UTC for most business logic, data storage, data exchange, and database. So, for that Instant

, that's all you need.

ZonedDateTime

If you need to customize in a time zone, for example to present to the user, apply ZoneId

to get ZonedDateTime

.

Specify the name of the current time zone in the format continent/region

, for example America/Montreal

, Africa/Casablanca

or Pacific/Auckland

. Never use the 3-4 letter abbreviation, for example EST

or IST

, as they are not real time zones and not standardized or even unique (!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

      



LocalDate

If you have a date-only value, parse it as an object LocalDate

.

LocalDate localDate = LocalDate.parse( "2002-09-24" );

      

To get the first moment of day for that date, specify the time zone. At any given moment, the date around the world changes by zone.

Also, don't assume the day starts on time 00:00:00

. Anomalies such as Daylight Saving Time (DST) can cause the first moment to become something like 01:00:00

. Let java.time define the first times of the day.

ZonedDateTime zdt = localDate.atStartOfDay( z );

      


About java.time

The java.time framework is built into Java 8 and later. These classes supersede the nasty old legacy datetime classes such as java.util.Date

, Calendar

and . SimpleDateFormat

The Joda-Time project , now in maintenance mode , advise moving to the java.time classes .

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

Where can I get the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is proof of possible future additions to java.time. Here you can find useful classes, such asInterval

,YearWeek

,YearQuarter

and longer .

+3


source


public class LocalDateTimeXmlAdapter extends XmlAdapter<String, LocalDateTime> {

    private static final Pattern ZONE_PATTERN = Pattern.compile("T.*(\\+|\\-|Z)");

    @Override
    public LocalDateTime unmarshal(String isoDateTime) throws Exception {
        LocalDateTime utcDateTime;
        if (ZONE_PATTERN.matcher(isoDateTime).matches()) {
            OffsetDateTime offsetDateTime = OffsetDateTime.parse(isoDateTime, DateTimeFormatter.ISO_DATE_TIME);
            ZoneOffset offset = offsetDateTime.getOffset();
            utcDateTime = offsetDateTime.toLocalDateTime().plusSeconds(offset.getTotalSeconds());
        } else {
            LocalDateTime localDateTime = LocalDateTime.parse(isoDateTime, DateTimeFormatter.ISO_DATE_TIME);
            ZoneId zoneId = ZoneId.systemDefault(); // TODO: Get ZoneId from userProfile
            ZoneOffset offset = ZonedDateTime.now(zoneId).getOffset();
            utcDateTime = localDateTime.minusSeconds(offset.getTotalSeconds());
        }
        return utcDateTime;
    }

    @Override
    public String marshal(LocalDateTime utcDateTime) throws Exception {
        ZoneId zoneId = ZoneId.systemDefault(); // TODO: Get ZoneId from userProfile
        ZoneOffset offset = ZonedDateTime.now(zoneId).getOffset();
        return utcDateTime.plusSeconds(offset.getTotalSeconds()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

}

      

-1


source







All Articles