2015-05-28 1 views
18

Я заметил, что java.time.format.DateTimeFormatter не может разобрать, как ожидалось. Смотрите ниже:DateTimeFormatter месяц шаблон буква «L» не работает

import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 

public class Play { 
    public static void tryParse(String d,String f) { 
    try { 
     LocalDate.parse(d, DateTimeFormatter.ofPattern(f)); 
     System.out.println("Pass"); 
    } catch (Exception x) {System.out.println("Fail");} 
    } 
    public static void main(String[] args) { 
    tryParse("26-may-2015","dd-L-yyyy"); 
    tryParse("26-May-2015","dd-L-yyyy"); 
    tryParse("26-may-2015","dd-LLL-yyyy"); 
    tryParse("26-May-2015","dd-LLL-yyyy"); 
    tryParse("26-may-2015","dd-M-yyyy"); 
    tryParse("26-May-2015","dd-M-yyyy"); 
    tryParse("26-may-2015","dd-MMM-yyyy"); 
    tryParse("26-May-2015","dd-MMM-yyyy"); 
    } 
} 

только последняя попытка с tryParse("26-May-2015","dd-MMM-yyyy"); будет "Pass". Согласно документации, LLL должен иметь возможность анализировать текстовый формат. Также не тонкая разница в верхнем регистре «M» и нижнем регистре «m».

Это действительно раздражает, так как я не могу по умолчанию разобрать строки, отформатированные по умолчанию, Oracle DB

SELECT TO_DATE(SYSDATE,'DD-MON-YYYY') AS dt FROM DUAL; 

Аналогично, для следующих программ:

import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 

public class Play { 
    public static void output(String f) { 
    LocalDate d = LocalDate.now(); 
    Locale l = Locale.US; 
    // Locale l = Locale.forLanguageTag("ru"); 
    System.out.println(d.format(DateTimeFormatter.ofPattern(f,l))); 
    } 
    public static void main(String[] args) { 
    output("dd-L-yyyy"); 
    output("dd-LLL-yyyy"); 
    output("dd-M-yyyy"); 
    output("dd-MMM-yyyy"); 
    } 
} 

я ниже выхода:

28-5-2015 
28-5-2015 
28-5-2015 
28-May-2015 

Очевидно, что спецификатор формата L не обрабатывает anyt Хин текстуальные, кажется числовая мне ...

Однако, если изменить локаль на Locale.forLanguageTag("ru"), я получаю следующий вывод:

28-5-2015 
28-Май-2015 
28-5-2015 
28-мая-2015 

Все очень интересно, что вы не согласны?

Вопросы у меня есть:

  • Разумно для меня ожидать, что каждый из должен работать?
  • Должны ли мы хотя бы представить некоторые из них как ошибку?
  • Не понимаю ли я использование спецификатора шаблона L.

Цитирование часть из документации, что я percieved как «это имеет значение»:

Текст: Стиль текста определяется на основе количества шаблонов букв, используемых. Менее 4 букв шаблонов будут использовать короткую форму. В точности 4 буквы будут использовать полную форму. Точно 5 рисунков буквы будут использовать узкую форму. Буквы шаблонов 'L', 'c' и 'q' определяют автономную форму стилей текста.

Номер: Если количество букв равно единице, то значение выводится с использованием минимального количества цифр и без заполнения. В противном случае в качестве ширины выходного поля используется счетчик цифр, при необходимости нулевое заполнение с нулевым запасом. Следующие буквы шаблонов имеют ограничений на количество букв. Можно указать только одну букву «c» и «F» . Можно указать до двух букв 'd', 'H', 'h', 'K', 'k', 'm', и 's'. Можно указать до трех букв «D».

номер/Текст:Если количество букв образца составляет 3 или выше, использовать правила текста выше. В противном случае используйте правила Number выше.

UPDATE

Я сделал два представления в Oracle:

  • Запрос Исправление для LLL (Long Form Text) вопрос: JDK-8114833 (оригинал оракул обзор ID: JI-9021661)
  • Запрос на усовершенствование для анализа синтаксиса в нижнем регистре: ID отзыва: 0 (это также ошибка?)
+2

Из моего (ограниченного) тестирования 'L' означает' 5' или '05' (май), где в качестве' M' может стоять '5' (M) или' 05' (ММ) или 'май '(МММ). Я думаю, что 'DateTimeFormatter' был очень строгим в его синтаксическом анализе, это ошибка или это то, как она была разработана? Трудно сказать прямо сейчас, но я бы сказал, что это дизайн. Выберите – MadProgrammer

+0

@MadProgrammer. В документации указано: «Буквы шаблонов« L »,« c »и« q »определяют автономную форму стилей текста». – YoYo

+2

Конечно, но из вашего теста и моего тестирования 'L' для чисел, но' M', в зависимости от того, сколько у вас может означать как числа, так и текст, попробуйте 'System.out.println (DateTimeFormatter.ofPattern (" dd -LLL-yyyy "). Format (LocalDate.now()));' and see;) – MadProgrammer

ответ

14

«автономное» название месяца

Я считаю, что «L» предназначен для языков, которые используют другое слово за месяц сам против, как он используется в данный момент. Например:

Locale russian = Locale.forLanguageTag("ru"); 

asList("MMMM", "LLLL").forEach(ptrn -> 
    System.out.println(ptrn + ": " + ofPattern(ptrn, russian).format(Month.MARCH)) 
); 

Выход:

MMMM: марта 
LLLL: Март 

Там не должно быть никаких причин, чтобы использовать 'L' вместо 'M' при анализе даты.

Я попытался следующим чтобы увидеть, какие поддержки локалей автономного месяца имя форматирование:

Arrays.stream(Locale.getAvailableLocales()) 
    .collect(partitioningBy(
       loc -> "3".equals(Month.MARCH.getDisplayName(FULL_STANDALONE, loc)), 
       mapping(Locale::getDisplayLanguage, toCollection(TreeSet::new)) 
    )).entrySet().forEach(System.out::println); 

на следующих языках получить локализованный автономное название месяца от «LLLL»:

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

Все остальные языки получают «3» в качестве автономного имени на март.

+0

Ваш выход для марта - это считается 4 или 5 символами на русском языке? Почему MMMM выводит 5 против LLLL 4 ...? – YoYo

+3

From DateTimeFormatter javadoc: «В точности 4 буквы будут использовать полную форму». Например, '.ofPattern (" MMMM "). Format (Month.DECEMBER)' будет производить «December» – Misha

+0

Хорошо ... У меня есть текущая дата (месяц может) в локали «ru», я получаю действительно интересные результаты ... обновил вопрос. – YoYo

3

По Javadocs:

шаблон буквы «L», «с» и «д» указать автономную форму текстовых стилей.

Однако я не мог найти много информации о том, что такое «автономная» форма. Глядя на код, который я вижу, что с помощью «L» выбирает TextStyle.SHORT_STANDALONE и в соответствии с этим Javadoc:

Краткий текст для автономного использования, как правило, аббревиатура. Например, день недели в понедельник может выводить «Mon».

Однако, это не так, как это работает. Даже с тремя буквами я получаю числовой вывод из этого кода:

DateTimeFormatter pattern = DateTimeFormatter.ofPattern ("dd-LLL-yyyy"); 
System.out.println (pattern.format (LocalDate.now())); 

Редактировать

После дальнейшего расследования кажется (насколько я могу сказать), что «автономный» версия этих кодов для тех случаев, когда вы хотите загрузить свои независимые от языка данные, предположительно используя DateTimeFormatterBuilder. Таким образом, по умолчанию DateTimeFormatter не имеет загруженных записей для TextStyle.SHORT_STANDALONE.

+0

Спасибо, я обновил свой вопрос с некоторыми отзывами. Я просто хочу медленно получить полную документацию по проблеме, поэтому я могу легко представить ее как ошибку (не чувствую себя плохо, я просто копирую ее plse). – YoYo

+2

@JoD. Я обновил свой ответ с небольшой дополнительной информацией. Надеюсь, это немного поможет, но кажется, что вы можете просто рассчитывать на некондиционные коды, если вам не нужна независимость от языка и готовы выполнить дополнительную работу, необходимую для того, чтобы все работало так, как вы хотите. – neuronaut

+0

Не уверен, что все это значит (автономно и т. Д.). Тем не менее - я пытался заставить locale-независимость жестко кодировать Locale.US ... все тот же результат. – YoYo