简体   繁体   中英

Parse string to date of specific format

I have a string with the following format String stringDate = "2019-04-25T07:03:17.428Z"; and I need to convert it to a LocalDateTime object of format 2019-04-25 07:03:17

I have tried with LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) but I get this parse exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-04-25T07:03:17.428Z' could not be parsed at index 10
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at com.company.Main.main(Main.java:12)

What would be the way to convert to specific format?

What you asked for (but don't want)

    String stringDate = "2019-04-25T07:03:17.428Z";
    LocalDateTime ldt = LocalDateTime.parse(stringDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
            .truncatedTo(ChronoUnit.SECONDS);
    System.out.println(ldt);

Output is

2019-04-25T07:03:17

It gives you what you said you wanted, but as rzwitserloot points out in the other answer , it does not make sense. It ignores the offset Z that was in your string. The offset is crucial for interpreting the date and time as a point in time. If the string had been 2019-04-25T07:03:17.428+13:00 instead, you would still have got the same output even though the string denotes a point in time that is 13 hours earlier.

The call to truncatedTo() gets rid of the fraction of second. If you can live with that fraction of second, leave out that call.

What you may want instead

For a more sensible conversion:

    ZoneId zone = ZoneId.of("Europe/Zagreb");
    
    Instant pointInTime = Instant.parse(stringDate);
    LocalDateTime ldt = pointInTime.atZone(zone)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in %s: %s%n", zone, ldt);

Date and time in Europe/Zagreb: 2019-04-25T09:03:17

Now the time 07:03 UTC has been converted to 09:03 Central European Summer Time.

Edit: If you positively need a LocalDateTime in UTC, for example for a database column requiring this, you may make this fact explicit in your code in this way:

    LocalDateTime ldt = pointInTime.atOffset(ZoneOffset.UTC)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in UTC: %s%n", ldt);

Date and time in UTC: 2019-04-25T07:03:17

What went wrong in your code?

To understand what failed for you let's look at the exception message you got:

Text '2019-04-25T07:03:17.428Z' could not be parsed at index 10

Index 10 is where the T that signifies the start of the time part is. Let's compare to your format pattern string: yyyy-MM-dd HH:mm:ss . This has a space instead of a T before the time part. This was the reason for the exception. If you needed to specify in the pattern that a T must be there, we would need to enclose it in single quotes, for example yyyy-MM-dd'T'HH:mm:ss .

Your input, fundamentally, isn't an LDT. It's a ZDT - that Z is a zone (ZonedDateTime). Thus, it is not possible to convert this string directly to an LDT, and that's good, because that'd make no sense.

Convert it to a ZDT. Then convert that to an LDT. It's a single method call.

You can parse it first using java.time.Instant and then use method ofInstant of java.time.LocalDateTime example:

String stringDate = "2019-04-25T07:03:17.428Z";
var instant = Instant.parse(stringDate);
var localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

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