Format date from String to LocalDate - java

I have a problem parsing a String to LocalDate.
According to similar questions on Stackoverflow and documentation I am using the correct values ​​dd (day of the month), MM (month of the year) and yyyy (year).
My String
String mydate = "18.10.2022 07:50:18";
My parsing test code
System.out.println(
LocalDate.parse(testPasswordExp)
.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")
)
);
Error:
Caused by: java.lang.RuntimeException:
java.time.format.DateTimeParseException:
Text '18.10.2022 07:50:18' could not be parsed at index 0

The main problem of your code example is that you first parse the String to a LocalDate without the use of a suitable DateTimeFormatter and then format() it with a DateTimeFormatter that tries to format hour of day, minute of hour and second of minute which just aren't there in a LocalDate.
You can parse this String to a LocalDate directly, but better parse it to a LocalDateTime because your String contains more than just information about
day of month
month of year
year
Your myDate (and probably the testPasswordExp, too) has a time of day. You can get a LocalDate as the final result that way, too, because a LocalDateTime can be narrowed down toLocalDate().
A possible way:
public static void main(String[] args) {
// example datetime
String testPasswordExp = "18.10.2022 07:50:18";
System.out.println(
LocalDateTime // use a LocalDateTime and…
.parse( // … parse …
testPasswordExp, // … the datetime using a specific formatter,
DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss")
).toLocalDate() // then extract the LocalDate
);
}
Output:
2022-10-18

You don't use the specified format for parsing, you use it to format the parsed date.
LocalDate.parse(mydate)
… uses the default ISO_LOCAL_DATE format. You are looking for this overload:
LocalDate.parse(mydate, DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
This method uses the specified format for parsing string to date. See this code run at Ideone.com.
Note that you are using LocalDate, meaning it will throw away the time part, keeping only the date after parsing. You probably meant to use LocalDateTime.

You can use
String mydate = "18.10.2022 07:50:18";
LocalDate ld = LocalDate.parse(mydate, DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));
System.out.println(ld.toString());

Related

Get 1 year back dateTime from current dateTime in yyyy-MM-dd HH:mm:ss.SSS format

I need to get the datetime of 1 year back considering the current datetime. The format needed to be in "yyyy-MM-dd HH:mm:ss.SSS"
ex : 2019-08-13 12:00:14.326
I tried following. But getting an error.
LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.parse(now.toString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")).minusYears(1);
Below Exception returned:
DateTimeParseException: Text '2020-08-13' could not be parsed
What's the best way to do this in Java 8+ ?
A LocalDate does not hold any information about hours, minutes, seconds or any unit below, instead, it holds information about year, month and day. By calling LocalDate.now() you are getting the date of today (the day of code execution).
If you need the time as well, use a LocalDateTime, which has a method now(), too, and actually consists of a LocalDate and a LocalTime.
Your error message tells you that the content of a LocalDate cannot be formatted using the given pattern (-String) "yyyy-MM-dd HH:mm:ss.SSS" because that pattern requires values for hours (HH), minutes (mm), seconds (ss) and milliseconds (SSS are fraction of seconds and three of them make it be milliseconds).
For parsing Strings or formatting datetimes, a LocalDateTime may be suitable but if you want to reliably add or subtract a year or any other amount of time, you'd rather use a class that considers time zones, offsets and daylight saving like ZonedDateTime or OffsetDateTime...
The LocalDate is the wrong class for your requirement as it does not hold the time information. You can use LocalDateTime but I suggest you use OffsetDateTime or ZonedDateTime so that you can get the flexibility of using the Zone Offset and Zone ID. Check https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html for an overview of date-time classes.
Also, keep in mind that a date or time or date-time object is an object that just holds the information about date/time; it doesn't hold any information about formatting and therefore no matter what you do when you print their objects, you will always get the output what their toString() methods return. In order to format these classes or in other words, to get a string representing a custom format of these objects, you have formatting API (e.g. the modern DateTimeFormatter or legacy SimpleDateFormat) at your disposal.
A sample code:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Get the current date & time at UTC
OffsetDateTime odtNow = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Now at UTC: " + odtNow);
// Get the date & time one year ago from now at UTC
OffsetDateTime odtOneYearAgo = odtNow.minusYears(1);
System.out.println("One year ago at UTC: " + odtNow);
// Define a formatter for the output in the desired pattern
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// Format the date & time using your defined formatter
String formattedDateTimeOneYearAgo = formatter.format(odtOneYearAgo);
System.out.println("Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: " + formattedDateTimeOneYearAgo);
}
}
Output:
Now at UTC: 2020-08-13T08:50:36.277895Z
One year ago at UTC: 2020-08-13T08:50:36.277895Z
Date Time in the pattern, yyyy-MM-dd HH:mm:ss.SSS: 2019-08-13 08:50:36.277
May not be the best way, but this will do it
LocalDateTime date = LocalDateTime.now().minusYears(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(date.format(formatter));
You say you want date+time from 1 year back, but you give it only a date (LocalDate). If you just want the date, all you need to do is:
LocalDate now = LocalDate.now();
LocalDate then = now.minusYears(1);
And if you want the timestamp also, then:
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.minusYears(1);
And so on for other objects.
As mentioned you should use LocalDateTime instead of LocalDate.
Your exception was thrown because your input String is in ISO_DATE_TIME format
Java Doc
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String now = dateTimeFormatter.format(LocalDateTime.now());
LocalDateTime localDate = LocalDateTime.parse(now, dateTimeFormatter);

Java 8 DateTimeFormatter to ignore millisecond and zone

I am struggling with Java 8 DateTimeFormatter.
I would like to convert a given String to dateFormat and parse to LocalDateTime
Here is my code
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
String text = "2020-01-01T01:01:11.123Z"
LocalDateTime date = LocalDateTime.parse(text, f)
But Java throws
Text could not be parsed, unparsed text found at index 19
If I change ofPattern to yyyy-MM-dd'T'HH:mm:ss.SSSX, my code executes without any error.
But I don’t want to use millisecond and time zone.
Do this instead:
String text = "2020-01-01T01:01:11.123Z";
LocalDateTime date = ZonedDateTime.parse(text)
.toLocalDateTime();
To get rid of the milliseconds information, do:
LocalDateTime date = ZonedDateTime.parse(text)
.truncatedTo(ChronoUnit.SECONDS)
.toLocalDateTime();
You can also use OffsetDateTime in place of ZonedDateTime.

parse String variable from database (type datetime) to LocalDateTime variable using Resultset

I'm trying to convert a String value (initially a LocalDateTime variable) that was stored in a database (as datetime) and parse it into a LocalDateTime variable. I've tried it with a formatter:
String dTP;
dTP=(rs.getString("arrivedate"));
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime dateTimeParked = LocalDateTime.parse(dTP,formatter);
And without a formatter:
String dTP;
dTP=(rs.getString("arrivedate"));
LocalDateTime dateTimeParked = LocalDateTime.parse(dTP);
But I get the same error each time:
Exception in thread "AWT-EventQueue-0" java.time.format.DateTimeParseException: Text '2016-07-09 01:30:00.0' could not be parsed at index 10
My thinking is that index 10 is the space between date and time.
Could anyone help me with this? I've been at it for hours :(
There is a error in the format of the that causes the issue. Please refer https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html.The ISO date time is of the format '2011-12-03T10:15:30' . The following will give you the idea
public static void main(String[] args) throws Exception {
String isoDate = "2016-07-09T01:30:00.0";
// ISO Local Date and Time '2011-12-03T10:15:30'
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime dateTimeParked = LocalDateTime.parse(isoDate, formatter);
System.out.println(dateTimeParked);
String date = "2016-07-09 01:30:00.0";
DateTimeFormatter formatterNew = DateTimeFormatter.ofPattern("yyyy-LL-dd HH:mm:ss.S");
LocalDateTime dateTimeParkedNew = LocalDateTime.parse(date, formatterNew);
System.out.println(dateTimeParkedNew);
}
This prints :
2016-07-09T01:30
2016-07-09T01:30
The other answers are correct, your string is in SQL format which differs from the canonical version of ISO 8601 format by using a space character in the middle rather than a T. So either replace the space with a T or define a formatting pattern for parsing.
Use smart objects, not dumb strings
But the bigger problem is that you are retrieving the date-time value from your database as a string. You should be retrieving date-time types of data as date-times types in Java.
For drivers compliant with JDBC 4.2 and later, you should be able to use setObject and getObject with java.time objects.
For SQL type of TIMESTAMP WITHOUT TIME ZONE use LocalDateTime. For TIMESTAMP WITH TIME ZONE, use Instant or perhaps ZonedDateTime depending on the database.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class );
Store in database.
myPreparedStatement.setObject( … , ldt ) ;
try this formatter:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
I'm not sure about the millisecond part though (In case it is more than 1 character long).

How to parse an ISO date with LocalDateTime.parse(...)

I want to parse a date string like 2011-11-30 like this:
LocalDateTime.parse("2011-11-30", DateTimeFormatter.ISO_LOCAL_DATE)
But I get the following exception:
java.time.format.DateTimeParseException: Text '2011-11-30' could not be parsed:
Unable to obtain LocalDateTime from TemporalAccessor
If I pass a date and time string everything works as expected:
LocalDateTime.parse("2011-11-30T23:59:59", DateTimeFormatter.ISO_LOCAL_DATE_TIME)
How can I parse a date like 2011-11-30 to a LocalDateTime (with a default time)?
As #JB Nizet suggested, the following works
LocalDate localDate = LocalDate.parse("2011-11-30", DateTimeFormatter.ISO_LOCAL_DATE);
LocalDateTime localDateTime = localDate.atTime(23, 59, 59);
System.out.println(localDateTime); // 2011-11-30T23:59:59
How can I parse a date like 2011-11-30 to a LocalDateTime (with a default time)?
Parse it first in a LocalDate
Use LocalDateTime atTime() method to set your default time
Note: Use of DateTimeFormatter.ISO_LOCAL_DATE is superfluous for parse(), see API LocalDate#parse()
The sample below use some magic numbers, wich should be avoid (What is a magic number, and why is it bad?).
Instead of using the method atTime(hour, minute, second),
LocalDate localDate = LocalDate.parse("2011-11-30", DateTimeFormatter.ISO_LOCAL_DATE);
LocalDateTime localDateTime = localDate.atTime(23, 59, 59);
you can use the LocalTime constants, such as LocalTime.MAX, (23:59:59), LocalTime.MIN (00:00:00), LocalTime.MIDNIGHT (23:59:59) or LocalTime.NOON (12:00:00)
LocalDate localDate = LocalDate.parse("2011-11-30", DateTimeFormatter.ISO_LOCAL_DATE);
LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);
It is better for maintainability and cross-reference.
Why I've written this answer despite existing answers
Unfortunately, all of the existing answers are only partially correct. They lack the following important aspects of the modern date-time API:
Using ISO format while parsing a date string
How to apply the current time to an instance of LocalDateTime to get a new instance of LocalDateTime with the current time
Question posted by OP:
How can I parse a date like 2011-11-30 to a LocalDateTime (with a
default time)?
Answer
There are two problems with your approach:
Since you are parsing a date string, you should have used LocalDate#parse instead of LocalDateTime#parse.
Since your date string is already in the ISO pattern, you need not specify this pattern using DateTimeFormatter explicitly as LocalDate.parse uses this pattern by default.
Apart from these two problems, you will need to use LocalDateTime#with to apply the current time to an instance of LocalDateTime to get a new instance of LocalDateTime with the current time.
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
// No need to specify DateTimeFormatter as the string is already in ISO format
LocalDate date = LocalDate.parse("2011-11-30");
System.out.println(date);
// Get LocalDateTime from LocalDate
LocalDateTime ldt = date
.atStartOfDay() //Convert to LocalDateTime with 00:00
.with(LocalTime.now()); //Adjust to current time
System.out.println(ldt);
}
}
Output:
2011-11-30
2011-11-30T11:53:39.103150
Note: Learn more about the modern date-time API from Trail: Date Time.

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