String Month-Year to Local Date - java

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

Related

I try to convert a String to Date format in java but has an exception

I try to convert String to Date format but I got an exception!
Here is my code:
SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yyyy");
startDate = format.parse(startDateString);
it should convert "14-MAY-2004" to Date. Thanks.
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work.
DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("d-MMM-uuuu")
.toFormatter(Locale.ENGLISH);
String startDateString = "14-MAY-2004";
LocalDate startDate = LocalDate.parse(startDateString, dateFormatter);
System.out.println(startDate);
Output is:
2004-05-14
Only if you indispensably need a Date object for a legacy API not yet upgraded to java.time, convert:
Instant startOfDay = startDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
Output in my time zone:
Fri May 14 00:00:00 CEST 2004
What went wrong in your code?
It’s almost certainly a locale problem. You didn’t specify a locale and hence no language for the month name or abbreviation. Always do that when the date string includes text in some language. Your SimpleDateFormat was using the default formatting locale of your JVM, and if that was a non-English-speaking locale, parsing was deemed to fail with an exception as you mentioned.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Similar question: Java - Unparseable date
From the statment "it should convert 14-MAY-2004 to date" i assume your input string is 14-MAY-2004 and you want this string to be converted to Date
String js="14-May-2004";
Date dt=new Date(js);
LocalDateTime localDateTime=dt.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
localDateTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));//or in the same format use- "dd-MMM-yyyy"

How to convert dd/MM/yyyy HH:mm:ss to offsetdatetime - java

I upgraded to:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern ("dd/MM/yyyy HH:mm:ss");
org.threeten.bp.LocalDateTime _date = org.threeten.bp.LocalDateTime.parse ("10/19/2020 18:00:47", dtf);
and get:
2020-10-19T18:00:47
but I still don't have an exit with the standard: 2020-10-19T18:00:47.868-03:00
The previously accepted answer by user3197884 is correct and informative (+1). I didn’t feel it fully answered the question as asked, so I wanted to contribute the conversion into an org.threeten.bp.OffsetDateTime.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern ("MM/dd/yyyy HH:mm:ss");
OffsetDateTime date = LocalDateTime.parse("10/19/2020 18:00:47", dtf)
.atZone(ZoneId.of("America/Argentina/Buenos_Aires"))
.toOffsetDateTime();
System.out.println(date);
Output is what you asked for:
2020-10-19T18:00:47-03:00
Since your string doesn’t have an offset or time zone in it, we need to provide the offset in some other way. Exactly which is the best way in your particular situation I dare not tell, but a very common good way is providing the time zone that was assumed for the string. I just picked one, please insert your own time zone instead.
Rather than swapping 10 and 19 in the string I have swapped dd and MM in the format pattern. Obviously either works.
Your DateTimeFormatter has ("dd/MM/yyyy HH:mm:ss") but you have used "10/19/2020 18:00:47".
Month cannot be 19.
Change your input to "19/10/2020 18:00:47" and it should work.
org.threeten.bp.format.DateTimeFormatter dtf = org.threeten.bp.format.DateTimeFormatter.ofPattern ("dd/MM/yyyy HH:mm:ss");
org.threeten.bp.LocalDateTime _date = org.threeten.bp.LocalDateTime.parse("19/10/2020 18:00:47", dtf);
System.out.println(_date);

Date format parse 2019-08-07T20:11:59.6250889+09:30 to UTC Java LocalDateTime

I tried to convert date string 2019-08-07T20:11:59.6250889+09:30
to LocalDateTime format yyyy-MM-dd HH:mm:ss format
String date = "2019-08-07T20:11:59.6250889+09:30";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
LocalDateTime startDate = LocalDateTime.parse(date, format);
Stack Trace
Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-08-07T20:11:59.6250889+09:30' could not be parsed at index 23
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
at Testing.main(Testing.java:11)
Your format is built-in.
String date = "2019-08-07T20:11:59.6250889+09:30";
DateTimeFormatter format = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
LocalDateTime startDate = LocalDateTime.parse(date, format);
System.out.println(startDate);
Output:
2019-08-07T20:11:59.625088900
The format is ISO 8601. Formatters for the most important variants of ISO 8601 are built into java.time. So don’t struggle with writing your own format pattern string. Just use the predefined DateTimeFormatter.ISO_OFFSET_DATE_TIME.
#shmosel is correct in the comment: DateTimeFormatter takes the number of decimals literally, so to parse a fraction of 7 decimals you would have needed SSSSSSS (7 S). java.time also has got the capability of parsing a variable number of decimals. For that you would need a DateTimeFormatterBuilder and its appendFraction method.
By your question title did you mean that you wanted the time in UTC? That would require an explicit conversion (since your string is at offset +09:30 from UTC):
LocalDateTime startDate = OffsetDateTime.parse(date)
.withOffsetSameInstant(ZoneOffset.UTC)
.toLocalDateTime();
2019-08-07T10:41:59.625088900
Links
Wikipedia article: ISO 8601
Documentation of DateTimeFormatter.ISO_OFFSET_DATE_TIME

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);

How to parse month full form string using DateFormat in Java?

I tried this:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy");
Date d = fmt.parse("June 27, 2007");
error:
Exception in thread "main" java.text.ParseException: Unparseable date: "June 27, 2007"
The java docs say I should use four characters to match the full form.
I'm only able to use MMM successfully with abbreviated months like "Jun" but i need to match full form.
Text: For formatting, if the number
of pattern letters is 4 or more, the
full form is used; otherwise a short
or abbreviated form is used if
available. For parsing, both forms are
accepted, independent of the number of
pattern letters.
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
You are probably using a locale where the month names are not "January", "February", etc. but some other words in your local language.
Try specifying the locale you wish to use, for example Locale.US:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy", Locale.US);
Date d = fmt.parse("June 27, 2007");
Also, you have an extra space in the date string, but actually this has no effect on the result. It works either way.
LocalDate from java.time
Use LocalDate from java.time, the modern Java date and time API, for a date
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM d, u", Locale.ENGLISH);
LocalDate date = LocalDate.parse("June 27, 2007", dateFormatter);
System.out.println(date);
Output:
2007-06-27
As others have said already, remember to specify an English-speaking locale when your string is in English. A LocalDate is a date without time of day, so a lot better suitable for the date from your string than the old Date class. Despite its name a Date does not represent a date but a point in time that falls on at least two different dates in different time zones of the world.
Only if you need an old-fashioned Date for an API that you cannot afford to upgrade to java.time just now, convert like this:
Instant startOfDay = date.atStartOfDay(ZoneId.systemDefault()).toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
Output in my time zone:
Wed Jun 27 00:00:00 CEST 2007
Link
Oracle tutorial: Date Time explaining how to use java.time.
Just to top this up to the new Java 8 API:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("MMMM dd, yyyy").toFormatter();
TemporalAccessor ta = formatter.parse("June 27, 2007");
Instant instant = LocalDate.from(ta).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date d = Date.from(instant);
assertThat(d.getYear(), is(107));
assertThat(d.getMonth(), is(5));
A bit more verbose but you also see that the methods of Date used are deprecated ;-) Time to move on.
val currentTime = Calendar.getInstance().time
SimpleDateFormat("MMMM", Locale.getDefault()).format(date.time)

Categories