Ответ 1
Используйте DateFormat.getDateInstance(int style, Locale locale) вместо создания собственных шаблонов с SimpleDateFormat
.
Я пытаюсь отформатировать дату на Java по-разному на основе данной локали. Например, я хочу, чтобы английские пользователи видели "1 ноября 2009 года" (отформатировано "MMM d, yyyy" ) и норвежскими пользователями, чтобы увидеть "1. nov. 2009" ( "d. MMM. Yyyy" ).
Часть месяца работает нормально, если я добавлю язык в конструктор SimpleDateFormat, но как насчет остальных?
Я надеялся, что могу добавить строки формата в паре с локалями в SimpleDateFormat, но я не могу найти способ сделать это. Возможно ли, или мне нужно, чтобы мой код проверял локаль и добавлял соответствующую строку формата?
Используйте DateFormat.getDateInstance(int style, Locale locale) вместо создания собственных шаблонов с SimpleDateFormat
.
SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE dd MMM yyyy", Locale.ENGLISH);
String formatted = dateFormat.format(the_date_you_want_here);
Используйте стиль + язык: DateFormat.getDateInstance (стиль int, локаль Locale)
Проверьте http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html
Выполните следующий пример, чтобы увидеть различия:
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public class DateFormatDemoSO {
public static void main(String args[]) {
int style = DateFormat.MEDIUM;
//Also try with style = DateFormat.FULL and DateFormat.SHORT
Date date = new Date();
DateFormat df;
df = DateFormat.getDateInstance(style, Locale.UK);
System.out.println("United Kingdom: " + df.format(date));
df = DateFormat.getDateInstance(style, Locale.US);
System.out.println("USA: " + df.format(date));
df = DateFormat.getDateInstance(style, Locale.FRANCE);
System.out.println("France: " + df.format(date));
df = DateFormat.getDateInstance(style, Locale.ITALY);
System.out.println("Italy: " + df.format(date));
df = DateFormat.getDateInstance(style, Locale.JAPAN);
System.out.println("Japan: " + df.format(date));
}
}
Вывод:
United Kingdom: 25-Sep-2017
USA: Sep 25, 2017
France: 25 sept. 2017
Italy: 25-set-2017
Japan: 2017/09/25
LocalDate.now().format(
DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM )
.withLocale( new Locale( "no" , "NO" ) )
)
Проблемные классы java.util.Date
и SimpleDateFormat
теперь унаследованы, их заменили классы java.time.
LocalDate
Класс LocalDate
представляет значение только для даты без времени суток и без часового пояса.
Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а в Монреале-Квебеке все еще "вчера".
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
DateTimeFormatter
Используйте DateTimeFormatter
для генерации строк, представляющих только часть даты или часть времени.
Класс DateTimeFormatter
может автоматически локализоваться.
Для локализации укажите:
FormatStyle
для определения длины или сокращения строки.Locale
для определения (а) человеческого языка для перевода названия дня, названия месяца и т.д., И (б) культурных норм, решающих вопросы сокращения, капитализации, пунктуации и т.д.Пример:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL ).withLocale( l );
String output = ld.format( f );
Идя в другом направлении, вы можете разобрать локализованную строку.
LocalDate ld = LocalDate.parse( input , f );
Обратите внимание, что локаль и часовой пояс являются полностью ортогональными вопросами. Вы можете представить момент Монреаля на японском языке или момент Окленда в Новой Зеландии на языке хинди.
Другой пример: измените 6 junio 2012
(на испанском языке) на 2012-06-06
(стандартный формат ISO 8601). Классы java.time по умолчанию используют форматы ISO 8601 для анализа/генерации строк.
String input = "6 junio 2012";
Locale l = new Locale ( "es" , "ES" );
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "d MMMM uuuu" , l );
LocalDate ld = LocalDate.parse ( input , f );
String output = ld.toString(); // 2012-06-06.
Вот пример кода для автоматического просмотра результатов нескольких форматов в нескольких локалях.
EnumSet
- это реализация Set
, высоко оптимизированная как для низкого использования памяти, так и для быстрой скорости выполнения при сборе объектов Enum
. Итак, EnumSet.allOf( FormatStyle.class )
предоставляет нам коллекцию всех четырех FormatStyle
перечисления FormatStyle
для цикла. Для получения дополнительной информации см. Oracle Tutorial по типам enum.
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 );
List < Locale > locales = new ArrayList <>( 3 );
locales.add( Locale.CANADA_FRENCH );
locales.add( new Locale( "no" , "NO" ) );
locales.add( Locale.US );
// Or use all locales (almost 800 of them, for about 120K text results).
// Locale[] locales = Locale.getAvailableLocales(); // All known locales. Almost 800 of them.
for ( Locale locale : locales )
{
System.out.println( "------| LOCALE: " + locale + " — " + locale.getDisplayName() + " |----------------------------------" + System.lineSeparator() );
for ( FormatStyle style : EnumSet.allOf( FormatStyle.class ) )
{
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( style ).withLocale( locale );
String output = ld.format( f );
System.out.println( output );
}
System.out.println( "" );
}
System.out.println( "« fin »" + System.lineSeparator() );
Выход.
------| LOCALE: fr_CA — French (Canada) |----------------------------------
mardi 23 janvier 2018
23 janvier 2018
23 janv. 2018
18-01-23
------| LOCALE: no_NO — Norwegian (Norway) |----------------------------------
tirsdag 23. januar 2018
23. januar 2018
23. jan. 2018
23.01.2018
------| LOCALE: en_US — English (United States) |----------------------------------
Tuesday, January 23, 2018
January 23, 2018
Jan 23, 2018
1/23/18
« fin »
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытеснять неприятные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, и SimpleDateFormat
.
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск для многих примеров и объяснений. Спецификация JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
.
Где взять классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и другие.
Локализация строки даты:
Основываясь на redsonic post:
private String localizeDate(String inputdate, Locale locale) {
Date date = new Date();
SimpleDateFormat dateFormatCN = new SimpleDateFormat("dd-MMM-yyyy", locale);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
try {
date = dateFormat.parse(inputdate);
} catch (ParseException e) {
log.warn("Input date was not correct. Can not localize it.");
return inputdate;
}
return dateFormatCN.format(date);
}
String localizedDate = localizeDate("05-Sep-2013", new Locale("zh","CN"));
будет похож на 05- 九月 -2013
Это отобразит дату в соответствии с текущей локалью пользователя:
Чтобы вернуть дату и время:
import java.text.DateFormat;
import java.util.Date;
Date date = new Date();
DateFormat df = DateFormat.getDateTimeInstance();
String myDate = df.format(date);
31 декабря 1969 г. 19:00:02
Чтобы вернуть только дату, используйте:
DateFormat.getDateInstance()
31 декабря 1969 г.
String text = new SimpleDateFormat("E, MMM d, yyyy").format(date);
Стиль Java 8 для заданной даты
LocalDate today = LocalDate.of(1982, Month.AUGUST, 31);
System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.ENGLISH)));
System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.FRENCH)));
System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.JAPANESE)));
import java.time.format.DateTimeFormatter;
myDate.format(DateTimeFormatter.ofPattern("dd-MMM-YYYY",new Locale("ar")))