LocalDate DateTimeFormatter problems - java

I have read the manuals and I'm completely at a loss as to why this code does not work.
// Date Entered must be valid
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy")
.withResolverStyle(ResolverStyle.STRICT);
try {
String dateEntered = lossDateMonth + "/" + lossDateDay + "/" + lossDateYear; // Slash to match UI
System.out.println(dateEntered);
LocalDate dateParsed = LocalDate.parse(dateEntered, dateTimeFormatter);
The println statement prints: 07/29/2015
The last line throws an exception:
java.time.format.DateTimeParseException: Text '07/29/2015' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2015, DayOfMonth=29, MonthOfYear=7},ISO of type java.time.format.Parsed
I read the manual on this and it says this sort of thing happens if you try to resolve a date that does not exist, for example September 31st. Even in the error, the parser seems to understand that I am asking about July 29, 2015, so what am I doing wrong here?

Replace the pattern "MM/dd/yyyy" by "MM/dd/uuuu". Have a look in DateTimeFormatter and IsoChronology. The problem is that when using .withResolverStyle(ResolverStyle.STRICT) the formatter expects an unique identifier to the year which is provided by uuuu where yyyy is the year of era. This is to strictly validate the values. The uniqueness is given by the fact that uuuu can be negative.
Have a look here, here and here for related posts.

Related

String Month-Year to Local Date

I am trying to parse some date-string into a date value, however, using the below code, I am getting an exception:
My Code
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ofPattern("MMMM-YYYY"))
.toFormatter(Locale.ENGLISH);
LocalDate KFilter = LocalDate.parse("August-2021", formatter);
The error log is
java.time.format.DateTimeParseException: Text 'August-2021' could not be parsed:
Unable to obtain LocalDate from TemporalAccessor: {WeekBasedYear[WeekFields[SUNDAY,1]]=2021, MonthOfYear=8},
ISO of type java.time.format.Parsed
Can you please help me out on the same ?
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ofPattern("MMMM-uuuu"))
.toFormatter(Locale.ENGLISH);
LocalDate kFilter = YearMonth.parse("August-2021", formatter).atDay(1);
System.out.println(kFilter);
Output:
2021-08-01
What went wrong in your code?
There are two problems with your code:
Format pattern strings are case sensitive. Upper case YYYY is for week-based year and only useful with a week number. Use either lower case yyyy or uuuu.
Month and year do not define a date, so you cannot readily parse them into a LocalDate. I suggest you parse into a YearMonth and then convert. In the conversion you need to decise on a day of month. An alternative would be specifying a day of month through DateTimeFormatterBuilder.parseDefaulting().
Links
Related questions:
Difference between year-of-era and week-based-year?
uuuu versus yyyy in DateTimeFormatter formatting pattern codes in Java?
Java DateTimeFormatterBuilder with optional pattern results in DateTimeParseException

DateTimeParseException: Text '2019-06-07 12:18:16' could not be parsed

I have following code to convert an Instant to String then convert it back to I
String timestampString = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
LOGGER.info("timestampString: " + timestampString);
Instant instant =
LocalDateTime.parse(timestampString,
DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")).toInstant(ZoneOffset.UTC);
it print the timestampString as: 2019-06-07 12:45:57
and failed at parse the string:
java.time.format.DateTimeParseException: Text '2019-06-07 12:45:57' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MinuteOfHour=45, HourOfAmPm=0, NanoOfSecond=0, SecondOfMinute=57, MilliOfSecond=0, MicroOfSecond=0},ISO resolved to 2019-06-07 of type java.time.format.Parsed
why it cannot parse it even though that's the same format I convert the timestamp to?
Use HH for hour of day instead of hh
The problem that you are asking about is that you are using lowercase hh in your format pattern string (both times). You need uppercase HH for hour day from 00 through 23. hh is for hour within AM or PM from 01 through 12. So what went wrong was that java.time didn’t know whether 12 in your string referred to 12 AM or 12 PM and refused to make a guess for you.
If you read the exception message closely you will also notice that it says that HourOfAmPm=0 was parsed. It doesn’t say HourOfDay.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timestampString = LocalDateTime.now().format(formatter);
System.out.println("timestampString: " + timestampString);
Instant instant = LocalDateTime.parse(timestampString, formatter)
.toInstant(ZoneOffset.UTC);
System.out.println("instant: " + instant);
When I ran this snippet just now, I got this output:
timestampString: 2019-06-08 19:22:51
instant: 2019-06-08T19:22:51Z
This is wrong! I ran the snippet around 17:22 UTC, not 19:22. Since Denmark is still using summer time (damn), the local time here was 19:22, which was used for the result and translated into the same wall clock time in UTC, not the same instant. You should always pass your desired time zone to the now method to avoid such bugs. Since you wanted UTC:
String timestampString = LocalDateTime.now(ZoneOffset.UTC).format(formatter);
timestampString: 2019-06-08 17:27:57
instant: 2019-06-08T17:27:57Z
Still better, don’t use LocalDateTime for holding something that you want to use as a moment in time. Use Instant, OffsetDateTime or ZonedDateTime instead.
There is more information on using hh, HH or kk for formatting and parsing hour values in this question and its answers: Difference between java HH:mm and hh:mm on SimpleDateFormat. The question is asking about the notoriously troublesome SimpleDateFormat, but the answers are valid for DateTimeFormatter too.

Unable to obtain LocalDate from TemporalAccessor using quarters

I am trying to parse some date-string into a date value, however, using the below code, I am getting an exception:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("Q'Q'uuuu - MMM");
String d = "3Q2016 - Aug";
System.out.println(LocalDate.parse(d, formatter));
The exception is below
java.time.format.DateTimeParseException: Text '3Q2016 - Aug' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=8, QuarterOfYear=3, Year=2016},ISO of type java.time.format.Parsed
Looking at the exception, I see the correct data, but it is not able to be parsed for some reason.
Other similar topics i see suggest using LocalDate or LocalDateTime, but neither work.
Its because the specified string does not have a specific date to select. You probably need to use YearMonth instead of LocalDateTime and then convert it using YearMonth.atDay(1) to get the first day of the month.
As said in this answer, you need to specify a day to be able to parse to a LocalDate. So one solution is to parse to a YearMonth instead and convert to a LocalDate by specifying a day afterwards.
Or you create a DateTimeFormatter with a fixed day in the first place:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("Q'Q'uuuu - MMM")
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.toFormatter(Locale.US);
String d = "3Q2016 - Aug";
System.out.println(LocalDate.parse(d, formatter));
I used toFormatter(Locale.US) to make the example work in all environments. In an environment where the input string matches the current locale, you can use toFormatter() instead.
Try adding a Time part to the date -
String str = "2Q1986 - Apr - 08 T00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("Q'Q'yyyy - MMM - dd 'T'hh:mm");
LocalDate dateTime = LocalDate.parse(str, formatter);

Getting "parse exception"

I want to change the string into the date formate for that I am using SimpleDateFormat class. I am passing the string as String+Integer.toString(int) from list of strings and SimpleDateFormat pattern as an inputs.
Note: Instead of String+Integer.toString(int) if I pass actual string like "Jan 09 2019" successfully convert string into the date. I tried a lot with different things.
dateList is a list of "MMM dd" formate dates.
Adding year on that formate by doing dateList.get(5)+Integer.toString(year) which is giving me parse exception <<-- Instead of this if I hardcode the date like Jan 09 2019 converting string into the date.
finalDatesInMMMDDYYYYFormat is another list where I am saving the dates in MMM dd yyyy format.
Utils.parseDate is a method I wrote in Utils class where I mentioned try-catch block.
int year = 2019;
private List<String> dateList = new ArrayList<>();
private List<Date> finalDatesInMMMDDYYYYFormat = new ArrayList<>();
final String testString = dateList.get(5)+Integer.toString(year);
finalDatesInMMMDDYYYYFormat.add(Utils.parseDate(testString, new SimpleDateFormat("MMM dd yyyy")));
Expected: Change the string into the date and add it to finalDatesInMMMDDYYYYFormat
Actual: Getting parse exception.
java.time
int year = 2019;
DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMM dd")
.toFormatter(Locale.ENGLISH);
List<LocalDate> finalDatesWithoutFormat = new ArrayList<>();
String dateString = "JAN 09";
MonthDay md = MonthDay.parse(dateString, dateFormatter);
finalDatesWithoutFormat.add(md.atYear(year));
System.out.println(finalDatesWithoutFormat);
The output from this snippet is:
[2019-01-09]
java.time, the modern Java date and time API, includes a class for a date without year, MonthDay, which may serve your purpose better than an ordinary date. My code also shows how to supply a year to obtain a LocalDate (a date without time of day).
I recommend you don’t use Date and SimpleDateFormat. Those classes are poorly designed and long outdated, the latter in particular notoriously troublesome.
What went wrong in your code?
From the information you have provided it’s not possible to tell why your code didn’t work. Possible explanations include the following, but there might be others.
As rockfarkas said in another answer, when concatenating your strings you were not putting any space between day of month and year, but the format string you used for parsing required a space there.
If your month abbreviations are in English, for example, and your JVM’s default locale is not English, parsing will fail (except in the rare cases where the month abbreviation coincides). You should always give your formatter a locale to specify the language used in the string to be parsed (or produced).
As an aside, your variable name finalDatesInMMMDDYYYYFormat was misleading since a Date hasn’t got (cannot have) a format.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Another example of wrong locale causing date parsing to fail: Java - Unparseable date
If you want parse format "MMM dd yyyy", you should add an extra space to your test string like this:
final String testString = dateList.get(5) + ' ' + year;

Parsing from SimpleDateFormat to Date not working?

SimpleDateFormat df = new SimpleDateFormat();
Date lastLogin = null;
try {
String troubleChild = lineScanner.next();
lastLogin = df.parse(troubleChild);
} catch (ParseException e) {
System.out.println("ohnoes");
}
Hi I'm quite new to using the date functions and I've come up with a problem. I have a file that is being parsed into various variables and they all work except this one i can never get it so that it passes the try/catch clause i've looked up similar problems but none of them work on my code.(The date i am inputting is in the format: Mon, Oct 30 22:20:11 GMT 2017) please can I get some help and thanks for it!
Solution: java.time
Please don’t take the trouble with the long outmoded classes Date and SimpleDateFormat. Instead use java.time, the modern Java date and time API also known as JSR-310:
DateTimeFormatter dtf
= DateTimeFormatter.ofPattern("E, MMM d H:mm:ss z uuuu", Locale.UK);
String inputDate = "Mon, Oct 30 22:20:11 GMT 2017";
ZonedDateTime lastLogin = ZonedDateTime.parse(inputDate, dtf);
System.out.println(lastLogin);
This prints
2017-10-30T22:20:11Z[GMT]
Since dates and times may come in so many different textual formats, I am using a format pattern string to specify your particular format. For which letters you may use, and what difference it makes whether you use 1, 3 or 4 of the same letter, see the documentation. Beware that format pattern strings are case sensitive.
Problem: SimpleDateFormat
You used the no-arg SimpleDateFormat constructor. The way I read the documentation, this gives you the default date format for your locale. If your JVM is running UK locale, I believe the format goes like 28/11/17 10:57 — not much like the input format you were trying to parse. You can use System.out.println(df.format(new Date())); to find out. The usual SimpleDateFormat constructor to use would be SimpleDateFormat(String, Locale) so that you may again supply a format pattern string and a locale.

Categories