wilmol
wilmol

Reputation: 1900

Java8 equivalent of JodaTime DateTimeFormat.shortDate()

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

Answers (2)

Anonymous
Anonymous

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]");
  1. It covers more cases that your Joda-Time formatter. Maybe that’s good. Specifically your Joda-Time formatter insists on a slash / 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.
  2. While you do need [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).
  3. If you prefer only one format pattern string, I would expect d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] to work (except in hte cases where the year is omitted) (I haven’t tested).

Upvotes: 4

Ryuzaki L
Ryuzaki L

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

Related Questions