javaandroiddate-formatthreetenbp

Error org.threeten.bp.format.DateTimeParseException


I know that there is a lot of similar questions like this but cant apply these solutions on them. i am trying to transform date that i am getting from server int this format: 2019-07-26T02:39:32.4053394 and then i am trying to convert it to milliseconds like this:

private long convertTimeInMilliseconds(String date){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
    return OffsetDateTime.parse(date, formatter)
            .toInstant()
            .toEpochMilli();

}

in my onCreate i call this method:

datePickerDialog.getDatePicker().setMinDate(convertTimeInMilliseconds("2019-07-26T02:39:32.4053394"));

but keep getting Caused by: org.threeten.bp.format.DateTimeParseException: Text '2019-07-26T02:39:32.4053394' could not be parsed, unparsed text found at index 19 on .toInstant() I think that problem is in my formatter, but do not know how to solve this


Solution

  • tl;dr

    LocalDateTime
    .parse( "2019-07-26T02:39:32.4053394" )
    .atZone( 
        ZoneId.of( "Asia/Tokyo" ) 
    )
    .toInstant()
    .getEpochMilli() 
    

    Wrong formatting pattern

    Your input string has a fractional second. But your formatting pattern says to expect only whole seconds. So your formatting pattern does not match your input. Hence your error.

    Wrong type

    Your input string lacks an indicator of time zone or offset-from-UTC. You should parse such input as a LocalDateTime.

    Table of date-time types in Java, both modern and legacy

    ISO 8601

    Your input complies with the ISO 8601 standard for text formats. The standard formats are used by default in java.time when parsing/generating text. So no need to specify a formatting pattern.

    LocalDateTime ldt = LocalDateTime.parse( "2019-07-26T02:39:32.4053394" ) ;
    

    Not a moment

    Understand that such a value is inherently ambiguous. We cannot know if that text is meant to represent 2 AM in Tokyo Japan, 2 AM in Toulouse France, or 2 AM in Toledo Ohio US — all different moments, several hours apart. So a LocalDateTime does not represent a moment, is not a point on the timeline.

    Never use LocalDateTime to track when something specific has happened. To track a moment, use Instant, OffsetDateTime, or ZonedDateTime.

    Determine a moment

    If you know for certain that text was meant to represent a moment in a certain time zone, apply a ZoneId to get a ZonedDateTime. Then extract an Instant to adjust to UTC, and get your count of milliseconds since epoch reference of 1970-01-01T00:00Z.

    If your input string was meant to represent a moment as seen in UTC, apply ZoneOffset.UTC to get a OffsetDateTime. Then extract an Instant, and get your count of epoch millis.


    About java.time

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

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

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

    You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

    Where to obtain the java.time classes?

    Table of which java.time library to use with which version of Java or Android