Reputation: 1900
What is the Java8 java.time
equivalent of
org.joda.time.formatDateTimeFormat.shortDate()
I've tried below way, but it fails to parse values such as "20/5/2016" or "20/5/16".
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
Upvotes: 1
Views: 985
Reputation: 86148
You are correct: A Joda-Time DateTimeFormatter
(which is the type you get from DateTimeFormat.shortDate()
) parses more leniently than a java.time DateTimeFormatter
. In the English/New Zealand locale (en-NZ
) shortDate
uses the format pattern d/MM/yy
and parses both 20/5/2016
and 20/5/16
into 2016-05-20.
I frankly find it nasty that it interprets both two-digit and four-digit years into the same year. When the format specifies two-digit year, I would have expected four digits to be an error for stricter input validation. Accepting one-digit month when the format specifies two digits is lenient too, but maybe not so dangerous and more in line with what we might expect.
java.time too uses the format pattern d/MM/yy
(tested on jdk-11.0.3). When parsing is accepts one or two digits for day of month, but insist on two-digit month and two-digit year.
You may get the Joda-Time behaviour in java.time, but it requires you to specify the format pattern yourself:
Locale loc = Locale.forLanguageTag("en-NZ");
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("d/M/[yyyy][yy]", loc);
System.out.println(LocalDate.parse("20/5/2016", dateFormatter));
System.out.println(LocalDate.parse("20/5/16", dateFormatter));
Output is:
2016-05-20 2016-05-20
If you want an advanced solution that works in other locales, I am sure that you can write a piece of code that gets the format pattern from DateTimeFormatterBuilder.getLocalizedDateTimePattern
and modifies it by replacing dd
with d
, MM
with M
and any number of y
with [yyyy][yy]
. Then pass the modified format pattern string to DateTimeFormatter.ofPattern
.
Edit: I’m glad that you got something to work. In your comment you said that you used:
Stream<String> shortFormPatterns = Stream.of(
"[d][dd]/[M][MM]",
"[d][dd]-[M][MM]",
"[d][dd].[M][MM]",
"[d][dd] [M][MM]",
"[d][dd]/[M][MM]/[yyyy][yy]",
"[d][dd]-[M][MM]-[yyyy][yy]",
"[d][dd].[M][MM].[yyyy][yy]",
"[d][dd] [M][MM] [yyyy][yy]");
/
between the numbers and rejects either hyphen, dot or space. Also I believe that Joda-Time would object to the year being left out completely.[yyyy][yy]
, you don’t need [d][dd]
nor [M][MM]
. Just d
and M
suffice since they also accept two digits (what happens in your code is that for example [d]
parses either one or two digits, so [dd]
is never used anyway).d[/][-][.][ ]M[/][-][.][ ][yyyy][yy]
to work (except in hte cases where the year is omitted) (I haven’t tested).Upvotes: 4
Reputation: 39978
FormatStyle.SHORT
returns shortest format either dd/MM/yy
or d/M/yy
format, so you need to use pattern to get the customized format
LocalDate date = LocalDate.now();
System.out.println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))); //9/29/19
You can also use DateTimeFormatter.ISO_DATE
or DateTimeFormatter.ISO_LOCAL_DATE
to get the iso format like yyyy-MM-dd
, and also you can see the available formats in DateTimeFormatter
System.out.println(date.format(DateTimeFormatter.ISO_DATE)); //2019-09-29
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); //2019-09-29
If you want the custom format like yyyy/MM/dd
the use ofPattern
System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))); //2019/09/29
Upvotes: 2