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
Advertisement
Answer
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
.
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?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later – Part of the standard Java API with a bundled implementation.
- Java 9 brought some minor features and fixes.
- Java SE 6 and Java SE 7
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android (26+) bundle implementations of the java.time classes.
- For earlier Android (<26), the process of API desugaring brings a subset of the java.time functionality not originally built into Android.
- If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….