retrography
retrography

Reputation: 6822

Unable to obtain LocalDateTime from TemporalAccessor when parsing LocalDateTime (Java 8)

I am simply trying to convert a date string into a DateTime object in Java 8. Upon running the following lines:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dt = LocalDateTime.parse("20140218", formatter);

I get the following error:

Exception in thread "main" java.time.format.DateTimeParseException: 
Text '20140218' could not be parsed: 
Unable to obtain LocalDateTime from TemporalAccessor: 
{},ISO resolved to 2014-02-18 of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)

The syntax is identical to what has been suggested here, yet I am served with an exception. I am using JDK-8u25.

Upvotes: 269

Views: 293520

Answers (13)

Iulian David
Iulian David

Reputation: 1021

For what is worth if anyone should read again this topic(like me) the correct answer would be in DateTimeFormatter definition, e.g.:

private static DateTimeFormatter DATE_FORMAT =  
            new DateTimeFormatterBuilder().appendPattern("dd/MM/yyyy[ [HH][:mm][:ss][.SSS]]")
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .toFormatter(); 

One should set the optional fields if they will appear. And the rest of code should be exactly the same.

Edit : usefull thing from wittyameta comment :

Remember to add the parseDefaulting AFTER you have called appendPattern. Otherwise it'll give DateTimeParseException

Upvotes: 98

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79580

You do not need to define a DateTimeFormatter

You do not need to define a DateTimeFormatter to parse the given date string. You can use the OOTB (Out-Of-The-Box), DateTimeFormatter.BASIC_ISO_DATE to parse it.

Demo:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDate date = LocalDate.parse("20140218", DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(date);

        // In case you need an instance of LocalDateTime
        LocalDateTime ldt = date.atTime(LocalTime.MIN);
        System.out.println(ldt);
    }
}

Output:

2014-02-18
2014-02-18T00:00

ONLINE DEMO

Learn more about the modern Date-Time API* from Trail: Date Time.


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time. Check this answer and this answer to learn how to use java.time API with JDBC.

Upvotes: 4

Uhyon Chung
Uhyon Chung

Reputation: 31

In cases where you simply want to take a format (whether or not it has time) and want to parse to a LocalDateTime, you can do the following.

LocalDateTime parseDateTime(String dateTime, DateTimeFormatter fmt) {
  return fmt.parse(dateTime, t -> {
    LocalDate date = t.query(TemporalQueries.localDate());
    LocalTime time = t.query(TemporalQueries.localTime());
    return LocalDateTime.of(date, time != null ? time : LocalTime.MIDNIGHT);
  });
}

I needed this because I was getting the date/time pattern as a parameter for a custom Spark UDF.

Upvotes: 3

user486631
user486631

Reputation:

 DateTimeFormatter format = new DateTimeFormatterBuilder()
                            .appendPattern("yyyy-MM-dd")
                            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                            .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
                            .toFormatter();

Works for me

Upvotes: 7

beefsupreme
beefsupreme

Reputation: 135

I arrived at this problem because my input string didn't have a year in it:

input string: Tuesday, June 8 at 10:00 PM
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a", Locale.US);

I knew the year so I just appended it to get:

input string: Tuesday, June 8 at 6:30 PM 2021
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a uuuu", Locale.US);

Upvotes: 0

Jeff Cook
Jeff Cook

Reputation: 8814

This works fine

public class DateDemo {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm");
        String date = "16-08-2018 12:10";
        LocalDate localDate = LocalDate.parse(date, formatter);
        System.out.println("VALUE="+localDate);

        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
        LocalDateTime parse = LocalDateTime.parse(date, formatter1);
        System.out.println("VALUE1="+parse);
    }
}

output:

VALUE=2018-08-16
VALUE1=2018-08-16T12:10

Upvotes: 2

Vinay Kasarla
Vinay Kasarla

Reputation: 7

Try this one:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy"); 
LocalDate fromLocalDate = LocalDate.parse(fromdstrong textate, dateTimeFormatter);

You can add any format you want. That works for me!

Upvotes: -1

Øyvind Mo
Øyvind Mo

Reputation: 1317

If you really need to transform a date to a LocalDateTime object, you could use the LocalDate.atStartOfDay(). This will give you a LocalDateTime object at the specified date, having the hour, minute and second fields set to 0:

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime time = LocalDate.parse("20140218", formatter).atStartOfDay();

Upvotes: 115

prime
prime

Reputation: 15594

If the date String does not include any value for hours, minutes and etc you cannot directly convert this to a LocalDateTime. You can only convert it to a LocalDate, because the string only represent the year,month and date components it would be the correct thing to do.

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf); // 2018-03-06

Anyway you can convert this to LocalDateTime.

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf);
LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

Upvotes: 20

mawburn
mawburn

Reputation: 2346

For anyone who landed here with this error, like I did:

Unable to obtain LocalDateTime from TemporalAccessor: {HourOfAmPm=0, MinuteOfHour=0}

It came from a the following line:

LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy h:mm"));

It turned out that it was because I was using a 12hr Hour pattern on a 0 hour, instead of a 24hr pattern.

Changing the hour to 24hr pattern by using a capital H fixes it:

LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy H:mm"));

Upvotes: 50

ZeroOne
ZeroOne

Reputation: 3171

Expanding on retrography's answer..: I had this same problem even when using LocalDate and not LocalDateTime. The issue was that I had created my DateTimeFormatter using .withResolverStyle(ResolverStyle.STRICT);, so I had to use date pattern uuuuMMdd instead of yyyyMMdd (i.e. "year" instead of "year-of-era")!

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
  .parseStrict()
  .appendPattern("uuuuMMdd")
  .toFormatter()
  .withResolverStyle(ResolverStyle.STRICT);
LocalDate dt = LocalDate.parse("20140218", formatter);

(This solution was originally a comment to retrography's answer, but I was encouraged to post it as a stand-alone answer because it apparently works really well for many people.)

Upvotes: 41

Tom B
Tom B

Reputation: 2923

This is a really unclear and unhelpful error message. After much trial and error I found that LocalDateTime will give the above error if you do not attempt to parse a time. By using LocalDate instead, it works without erroring.

This is poorly documented and the related exception is very unhelpful.

Upvotes: 42

retrography
retrography

Reputation: 6822

It turns out Java does not accept a bare Date value as DateTime. Using LocalDate instead of LocalDateTime solves the issue:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate dt = LocalDate.parse("20140218", formatter);

Upvotes: 273

Related Questions