Java 8 date/time: instant, could not be parsed at index 19 - java

I have following piece of code:
String dateInString = "2016-09-18T12:17:21:000Z";
Instant instant = Instant.parse(dateInString);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
It gives me following exception:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '2016-09-18T12:17:21:000Z' could not be parsed at index 19 at
java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at
java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.Instant.parse(Instant.java:395) at
core.domain.converters.TestDateTime.main(TestDateTime.java:10)
When I change that last colon to a full stop:
String dateInString = "2016-09-18T12:17:21.000Z";
…then execution goes fine:
2016-09-18T15:17:21+03:00[Europe/Kiev]
So, the question is - how to parse date with Instant and DateTimeFormatter?

The "problem" is the colon before milliseconds, which is non-standard (standard is a decimal point).
To make it work, you must build a custom DateTimeFormatter for your custom format:
String dateInString = "2016-09-18T12:17:21:000Z";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_DATE_TIME)
.appendLiteral(':')
.appendFraction(ChronoField.MILLI_OF_SECOND, 3, 3, false)
.appendLiteral('Z')
.toFormatter();
LocalDateTime instant = LocalDateTime.parse(dateInString, formatter);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
Output of this code:
2016-09-18T12:17:21+03:00[Europe/Kiev]
If your datetime literal had a dot instead of the last colon, things would be much simpler.

Use a SimpleDateFormat:
String dateInString = "2016-09-18T12:17:21:000Z";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS");
Instant instant = sdf.parse(dateInString).toInstant();
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
2016-09-18T19:17:21+03:00[Europe/Kiev]

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy");
String date = "16/08/2016";
//convert String to LocalDate
LocalDate localDate = LocalDate.parse(date, formatter);
If the String is formatted like ISO_LOCAL_DATE, you can parse the String directly, no need conversion.
package com.mkyong.java8.date;
import java.time.LocalDate;
public class TestNewDate1 {
public static void main(String[] argv) {
String date = "2016-08-16";
//default, ISO_LOCAL_DATE
LocalDate localDate = LocalDate.parse(date);
System.out.println(localDate);
}
}
Check out this site
Site here

Related

Parse a String to LocaDateTime in Java

Consider a String "2022-03-23 21:06:29.4933333 +00:00".
How do I parse the above DateTimeOffset String to LocalDateTime in Java?
I tried with the following DateTimeFormatter but the format seems to be incorrect:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss\[.nnnnnnn\] \[+|-\]hh:mm\]");
LocalDateTime dateTime = LocalDateTime.parse(timestamp, formatter)
First, start by having the JavDocs for DateTimeFormatter at hand, this is going to really help determine which specifiers you need
The first thing to do is parse the text into a ZonedDateTime, LocalDateTime won't parse a input value with a time zone (AFAIK), you "might" be able to force it, but what's the point?
String text = "2022-03-23 21:06:29.4933333 +00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSS z");
ZonedDateTime zdt = ZonedDateTime.parse(text, formatter);
System.out.println(zdt);
This prints...
2022-03-23T21:06:29.493333300Z
Now you could use ZonedDateTime#toLocalDateTime, but this won't take into account the current time zone of the user/computer.
If you need to convert the ZonedDateTime to LocalDateTime, it's best to do so in away which will translate the time (and date if required) to best represent the time within the current time zone (okay, I was confused typing it)
For example, converting the input value into my current time zone (+11 hours) would look like this...
ZoneId currentZone = ZoneId.systemDefault();
ZonedDateTime currentZDT = zdt.withZoneSameInstant(currentZone);
System.out.println(currentZDT);
LocalDateTime ldt = currentZDT.toLocalDateTime();
System.out.println(ldt);
which will print...
2022-03-24T08:06:29.493333300+11:00[Australia/Melbourne]
2022-03-24T08:06:29.493333300
This means that at 9:06pm on the 23rd March in Grinch (GMT), it was 8:06am on the 24th March where I live.
Now you can use different ZoneIds to convert to a TimeZone which is not the current computers TimeZone, but I'll leave that up to you to experiment with (for example, I used Convert ZonedDateTime to LocalDateTime at time zone to base my example on)
You need create custom DateTimeFormatter:
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
public class Main {
public static void main(String args[]){
String dateString = "2022-03-23 21:06:29.4933333 +00:00";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_TIME)
.appendLiteral(' ')
.appendOffsetId()
.toFormatter();
//In case of OffSet matter, retaining the instant
LocalDateTime localDateTimeSavePointOfTime = OffsetDateTime.parse(dateString, formatter).withOffsetSameInstant(OffsetDateTime.now().getOffset()).toLocalDateTime();
//In case OffSet does not matter we can skip it
LocalDateTime localDateTimeSkipOffSet = LocalDateTime.parse(dateString, formatter);
}
}

java.time.format.DateTimeParseException: Text '10-03-2021' could not be parsed at index 0

I am trying to convert a string to date format with Java8 using DateTimeFormatter in spring boot, But I receive an error [[java.time.format.DateTimeParseException: Text '10-03-2021' could not be parsed at index 0]]. I am using LocalDate because I want my output to have only date without time. What Am I doing wrong in my code.
String date= "10-03-2021"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy",Locale.forLanguageTag("sw-TZ"));
LocalDateTime dateTime = LocalDateTime.parse(date, formatter);
System.out.println(dateTime.format(formatter));
You need to parse date in dd-MM-yyyy pattern first and then format it to the pattern of your choice.
String date= "10-03-2021";
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate localDate = LocalDate.parse(date, format);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy",Locale.forLanguageTag("sw-TZ"));
System.out.println(localDate.format(formatter));

not able to convert String "rejectedDate":"2018-03-29" to ZoneDate time format

java.time.format.DateTimeParseException: Text '2018-03-29 16:15:30'
could not be parsed at index 10
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
OffsetDateTime date =
OffsetDateTime.parse(entry.getValue(), fmt);
predicates.add(cb.equal(root.get(entry.getKey()), date));
You created a DateTimeFormatter with the pattern "yyyy-MM-dd" (year-month-day), but your input also contains "hours:minutes:seconds" (2018-03-29 16:15:30).
But even if you use the correct pattern, this will still throw an exception:
// now the pattern matches the input
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
OffsetDateTime date = OffsetDateTime.parse("2018-03-29 16:15:30", fmt); // DateTimeParseException
That's because an OffsetDateTime also needs the UTC offset, and the input doesn't have it. You have some alternatives:
parse it to a LocalDateTime:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse("2018-03-29 16:15:30", fmt);
if you really need OffsetDateTime, you'll have to arbitrarialy choose some offset for it. Example:
LocalDateTime date = // parse the LocalDateTime as above
// use offset +02:00
OffsetDateTime odt = date.atOffset(ZoneOffset.ofHours(2));
Or you can set a default value in the formatter:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time pattern
.appendPattern("yyyy-MM-dd HH:mm:ss")
// use some offset as default (0 is UTC)
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
OffsetDateTime odt = OffsetDateTime.parse("2018-03-29 16:15:30", fmt);

Java java.time.format.DateTimeParseException on String

I am trying to parse a date to convert it to epochs. I tried the solution of a similar question here without success:
String date = "Jun 4 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("LLL dd yyyy").withLocale(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(date, formatter);
System.out.println(date+" "+ldt.toEpochSecond(ZoneOffset.UTC));
And I get Exception in thread "main" java.time.format.DateTimeParseException: Text 'Jun 4 2015' could not be parsed at index 0 even though I am fairly certain that my regular expression is correct. What am I missing here?
EDIT:
Following the comments, I changed LocalDateTime to LocalDate, but keep getting the same error:
String date = "Jun 4 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy").withLocale(Locale.ENGLISH);
LocalDate ldt = LocalDate.parse(date, formatter);
String date = "Jun 4 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy").withLocale(Locale.ENGLISH);
LocalDate ldt = LocalDate.parse(date, formatter);
parses fine. Don't put the "dd" as it won't parse days less than 10. As #JB Nizet said, you'll need to use LocalDate, not LocalDateTime.

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.
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);
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();
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
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"));
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.
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.)
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
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.
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
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.
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
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!
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);

Categories

Resources