Эквивалент Java8 для JodaTime DateTimeFormat.shortDate()

Что такое Java8 java.time эквивалент

org.joda.time.formatDateTimeFormat.shortDate()

Я пробовал ниже, но не смог проанализировать такие значения, как «20/5/2016» или «20/5/16».

DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) 

person wilmol    schedule 30.09.2019    source источник


Ответы (2)


Вы правы: Joda-Time DateTimeFormatter (это тип, который вы получаете от DateTimeFormat.shortDate()) анализирует более снисходительно, чем java.time DateTimeFormatter. В английской/новозеландской локали (en-NZ) shortDate использует шаблон формата d/MM/yy и анализирует как 20/5/2016, так и 20/5/16 на 20 05 2016.

Честно говоря, я нахожу неприятным, что он интерпретирует как двузначные, так и четырехзначные годы в один и тот же год. Когда формат указывает год из двух цифр, я ожидал, что четыре цифры будут ошибкой для более строгой проверки ввода. Принятие однозначного месяца, когда формат указывает две цифры, тоже снисходительно, но, возможно, не так опасно и больше соответствует тому, что мы могли бы ожидать.

java.time также использует шаблон формата d/MM/yy (проверено на jdk-11.0.3). При синтаксическом анализе принимает одну или две цифры дня месяца, но настаивает на двухзначном месяце и двузначном годе.

Вы можете получить поведение Joda-Time в java.time, но для этого вам нужно указать шаблон формата самостоятельно:

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

Выход:

2016-05-20
2016-05-20

Если вам нужно расширенное решение, которое работает в других локалях, я уверен, что вы можете написать фрагмент кода, который получает шаблон формата из DateTimeFormatterBuilder.getLocalizedDateTimePattern и изменяет его, заменяя dd на d, MM на M и любое количество y на [yyyy][yy]. Затем передайте измененную строку шаблона формата в DateTimeFormatter.ofPattern.

Редактировать: я рад, что у вас есть работа. В своем комментарии вы сказали, что использовали:

    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. Он охватывает больше случаев, чем ваш форматировщик Joda-Time. Может быть, это хорошо. В частности, ваш форматировщик Joda-Time настаивает на косой черте / между числами и отклоняет дефис, точку или пробел. Также я считаю, что Joda-Time будет возражать против полного исключения года.
  2. Хотя вам нужно [yyyy][yy], вам не нужны ни [d][dd], ни [M][MM]. Достаточно только d и M, поскольку они также принимают две цифры (в вашем коде происходит то, что, например, [d] анализирует либо одну, либо две цифры, поэтому [dd] все равно никогда не используется).
  3. Если вы предпочитаете только одну строку шаблона формата, я ожидаю, что d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] будет работать (за исключением случаев, когда год опущен) (я не проверял).
person Ole V.V.    schedule 30.09.2019
comment
Да, [] работает отлично. Я просто использую 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]"); Может быть, более подробный, чем joda.time, который неявно поддерживает больше случаев, но java.time лучше в других областях. - person wilmol; 02.10.2019
comment
Спасибо, @wilmol, за продолжение. У меня было два комментария. Я добавил их в качестве редактирования внизу моего ответа. - person Ole V.V.; 02.10.2019
comment
@ОлеВ.В. d[/][-][.][ ]M[/][-][.][ ][yyyy][yy] работает очень хорошо. По крайней мере, для таких входов, как "20/5/2016", "20/5/16", "31.12.2009", "21 3 2017", "09/02/19", "1 5 20", "09 3 16". - person MC Emperor; 02.10.2019

FormatStyle.SHORT возвращает кратчайший формат в формате dd/MM/yy или d/M/yy, поэтому вам нужно использовать шаблон, чтобы получить настраиваемый формат.

LocalDate date = LocalDate.now();   
System.out.println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)));   //9/29/19

Вы также можете использовать DateTimeFormatter.ISO_DATE или DateTimeFormatter.ISO_LOCAL_DATE для получения формата iso, такого как yyyy-MM-dd, а также вы можете увидеть доступные форматы в DateTimeFormatter

System.out.println(date.format(DateTimeFormatter.ISO_DATE));       //2019-09-29
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); //2019-09-29

Если вам нужен пользовательский формат, например yyyy/MM/dd, используйте ofPattern

System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))); //2019/09/29
person Deadpool    schedule 30.09.2019
comment
Проблема в том, что я не знаю, в каком формате будет ввод. Кажется, JodaTime shortDate() охватывает больше случаев, чем java.time FormatStyle.SHORT. - person wilmol; 30.09.2019
comment
@wilmol Какие случаи, пожалуйста? Из документации DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) кажется эквивалентным DateTimeFormat.shortDate(). Я плохо знаю Joda-Time, поэтому могу что-то упустить. - person Ole V.V.; 30.09.2019