У меня есть этот небольшой фрагмент кода:
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) {
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
System.out.println(format.format(new Date()));
}
}
С Java 8 вывод:
Tue, 16 Jul 2019 13:16:54 AEST
С Java 11:
Tue., 16 Jul. 2019 13:16:54 AEST
В чем разница и как мне изменить свой код, чтобы он работал одинаково в обеих версиях Java?
На самом деле я использовал Руль, обнаружив эту проблему, и я мог сузить ее до версии Java, но было бы здорово знать, как использовать Handlebars для получения того же результата для той же строки формата...)
Какая у вас локаль по умолчанию? Также спрашиваю, потому что я не думаю, что встречал локаль, где точка (точка) после аббревиатур английского языка (Tue и Jul) была бы правильной.
Возможный дубликат JDK dateformatter анализирует DayOfWeek в немецкой локали, java8 против java9 и/или Анализ времени с помощью LocalTime. Короче говоря, это из-за CLDR.
Мой регион en_AU
Локаль, используемая в последней ссылке, stackoverflow.com/questions/56814020/…, тоже en-AU. Вы захотите прочитать комментарии, даже если они немного длинные.




Запустите Java 9 и более поздние версии (включая Java 11) с системным свойством java.locale.providers, определенным следующим образом:
java -Djava.locale.providers=COMPAT,CLDR YourApp
Теперь вывод без точек, в том же формате, что и на Java 8, например:
Tue, 16 Jul 2019 14:24:15 AEST
Java получает данные о локали, включая сокращения, используемые для дней недели и месяцев на разных языках, из четырех источников. До Java 8 по умолчанию использовались собственные данные локали Java. Данные локали из Java 8 из репозитория Unicode Common Locale Data Repository (CLDR; см. ссылки внизу) также включены, а из Java 9 они используются по умолчанию. Собственные данные Java по-прежнему включены и доступны, если указать COMPAT в вышеуказанном системном свойстве. Нам нужно поставить его первым в строке, так как источники проверяются по очереди.
Можно было бы ожидать, что другим (и, возможно, даже более приятным) решением будет использование CLDR во всех версиях Java. Любопытно, что в данном случае это не дает нам одинаковый формат для всех версий Java. Вот результат при установке свойства на CLDR,JRE (JRE — это старое название COMPAT, в Java 8 нам нужно использовать его вместо этого).
На Java 8:
Tue, 16 Jul 2019 14:35:02 AEST
На Java 9 и 11:
Tue., 16 Jul. 2019 14:35:52 AEST
CLDR поставляется в различных версиях, и разные версии Java включаются в разные версии.
Вот фрагмент, который я использовал для вышеуказанных выходных данных.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"EEE, dd MMM yyyy HH:mm:ss zzz", Locale.forLanguageTag("en-AU"));
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
System.out.println(now.format(formatter));
Я использую и рекомендую java.time, современный API даты и времени Java. Классы даты и времени, которые вы использовали, SimpleDateFormat и Date, давно устарели и всегда были плохо спроектированы, поэтому я рекомендую избегать их. В Java 8 и более поздних версиях, безусловно, нет причин, по которым мы должны их использовать, и java.time также был перенесен в Java 6 и 7.
LocaleServiceProvider документация указывает возможные источники данных локали: CLDR, COMPAT и другие.Большое спасибо за исчерпывающее объяснение - я ценю время, которое вы потратили на ответ. Это причина, по которой я посещаю (и публикую) stackoverflow! +1 за ваши забавные заголовки (tl;dr / cldr) :D
Я рекомендую вам не использовать
SimpleDateFormatиDate. Эти классы плохо спроектированы и давно устарели, а первые, как известно, доставляют много хлопот. Вместо этого используйтеDateTimeFormatterи, например,ZonedDateTime, оба из java.time, современный API даты и времени Java.