Как настроить форматирование даты и времени в Java, который соответствует настройкам пользовательской ОС

Я запускаю свое Java-приложение на компьютере под управлением Windows 7, где мои региональные настройки настроены на форматирование дат как YYYY-mm-dd и время как HH: mm: ss (например, "2011-06-20 07:50: 28" ). Но когда я использую DateFormat.getDateTimeInstance().format для форматирования своей даты, я не вижу, что вместо этого получаю "20 июня 2011 года 7:50:28". Что мне нужно сделать, чтобы отформатировать даты так, чтобы мои клиенты установили настройки своей ОС для отображения дат?

Вот как выглядит мой код:

File selGameLastTurnFile = selectedGame.getLastTurn ().getTurnFile ();
Date selGameModifiedDate = new Date (selGameLastTurnFile.lastModified());
if (selectedGame.isYourTurn ())  {
    gameInfo = Messages.getFormattedString ("WhoseTurnIsIt.Prompt.PlayTurn",  //$NON-NLS-1$
            FileHelper.getFileName (selGameLastTurnFile), 
            DateFormat.getDateTimeInstance().format(selGameModifiedDate));
}  else  {
    gameInfo = Messages.getFormattedString ("WhoseTurnIsIt.Prompt.SentTurn",  //$NON-NLS-1$
            selGameLastTurnFile.getName (), 
            DateFormat.getDateTimeInstance().format(selGameModifiedDate));
}

В вызовах Messages.getFormattedString используется MessageFormat, чтобы поместить дату в предложение, которое будет выглядеть следующим образом:

Слушайте ход "QB Nat vs Ian 008" (получен 20 июня 2011 года 7:50:28)

Однако настройки моей ОС настроены на форматирование даты, как я описал выше, и я ожидал увидеть это:

Сыграйте в ход "QB Nat vs Ian 008" (получен 2011-06-20 07:50:28)

Я искал здесь и других сайтов программирования Java и не мог найти ответ, но это похоже на такую ​​очевидную вещь, которая хочет сделать это, я чувствую, что мне не хватает чего-то очевидного.

Ответ 1

Вы не можете сделать это в чистой Java. Sun/Oracle не может сделать эту систему независимой.

Быстрый просмотр библиотек .NET дает эту страницу - цитата:

Пользователь может выбрать переопределение некоторых значений, связанных с текущей культурой Windows, с помощью региональных и языковых параметров панели управления. Например, пользователь может выбрать отображение даты в другом формате или использование валюты, отличной от значения по умолчанию для культуры. Если для свойства CultureInfo.UseUserOverride установлено значение true, свойства объекта CultureInfo.DateTimeFormat, объект CultureInfo.NumberFormat и объект CultureInfo.TextInfo также извлекаются из пользовательских настроек.

Я бы предположил, что вы делаете это так, чтобы система зависела от Windows, если вам нужна эта функциональность (например, для доступа к реестру Windows в качестве предложенного @laz).

Ответ 2

Сначала вы должны сказать Java, как выглядит ваша система LOCALE.

Проверить систему Java.
String locale = System.getProperty("user.language")

А затем отформатируйте дату (SimpleDateFormat)
SimpleDateFormat(String pattern, Locale locale)

Обратитесь к практическому Java-коду для рабочего примера...

String systemLocale = System.getProperty("user.language");
String s;
Locale locale; 

locale = new Locale(systemLocale );
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// system locale is PT outputs 16/Jul/2011

locale = new Locale("us");
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// outputs Jul 16, 2011

locale = new Locale("fr");
s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(new Date());
System.out.println(s);
// outputs 16 juil. 2011  

Ответ 3

Я нашел этот класс утилиты Java JetBrains, который извлекает все пользовательские настройки локали из ОС (как из Windows, так и из Mac) и делает правильное форматирование для вас:

https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/util/text/DateFormatUtil.java

Он под лицензией Apache 2.0, поэтому вы можете использовать его в своем проекте.

Ответ 4

Похоже, вам понадобится доступ к реестру Windows для этого. См. Этот вопрос для различных решений для чтения/записи в реестр Windows с использованием Java.

Как только вы выберете один из многих способов доступа к реестру, вам нужно будет получить правильный ключ из реестра для формата. В этом документе указывается, что ключ используется HKEY_USERS\.Default\Control Panel\International.

При использовании GNOME в Linux вы можете использовать команду gconftool, аналогичную команде reg для Windows, как указано в предыдущих ссылках о реестре Windows. Я вижу ключ /apps/panel/applets/clock_screen0/prefs/custom_format в моей конфигурации, хотя он пуст, так как я использую значение по умолчанию:

gconftool -g /apps/panel/applets/clock_screen0/prefs/custom_format

Я не уверен, что это значение, которое вы хотите использовать для своих целей или нет.

В Mac OS я не уверен, что вы будете делать.

Ответ 5

Oracle JDK 8 полностью поддерживает форматирование с использованием пользовательских региональных настроек ОС.

Просто установите системное свойство java.locale.providers=HOST

Согласно https://docs.oracle.com/javase/8/docs/technotes/guides/intl/enhancements.8.html:

HOST представляет текущую пользовательскую настройку базовых настроек операционной системы. Он работает только с пользовательским языком по умолчанию, а настраиваемые параметры могут различаться в зависимости от ОС, но в основном поддерживаются форматы Дата, Время, Число и Валюта.

Фактическая реализация этого форматера доступна в классе sun.util.locale.provider.HostLocaleProviderAdapterImpl. Если использование системного свойства недопустимо (скажем, вы не хотите влиять на все приложение), можно напрямую использовать этот класс провайдера. Класс является внутренним API, но может быть достигнут с помощью отражения:

private static DateFormat getSystemDateFormat() throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("sun.util.locale.provider.HostLocaleProviderAdapterImpl");
        Method method = clazz.getMethod("getDateFormatProvider");
        DateFormatProvider dateFormatProvider = (DateFormatProvider)method.invoke(null);
        DateFormat dateFormat = dateFormatProvider.getDateInstance(DateFormat.MEDIUM, Locale.getDefault(Locale.Category.FORMAT));
        return dateFormat;
    }

Ответ 6

Возможно, я не понимаю, что вы здесь делаете, но вам нужно использовать Locale.

 DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);

Используя Locale, вы можете управлять форматом для того региона, в котором вы используете.

Ответ 7

java -Djava.locale.providers=HOST,CLDR,COMPAT YourProgram

Форматы даты и времени являются частью данных локали Javas. Java может получать данные о локали из четырех источников. Какие из них он использует, java.locale.providers системным свойством java.locale.providers. По умолчанию до Java 8 был JRE,SPI. С Java 9 его CLDR,COMPAT. Ни один из них не даст вам данные о дате и времени из операционной системы, но вы можете получить их, предоставив поставщика локали HOST, например, как в командной строке выше. При запуске вашей программы с этим определением свойства вы можете, например, иметь:

    DateTimeFormatter systemFormatter
            = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Africa/Bangui"));
    String formattedDateTime = now.format(systemFormatter);
    System.out.println(formattedDateTime);

Это напечатает текущую дату и время в формате, определенном базовой операционной системой. Если операционная система поддерживает его, вы можете изменять длину вывода, используя стили форматирования FULL, LONG, MEDIUM и SHORT.

Для большинства целей вам понадобится DateTimeFormatter знающий формат, как в приведенном выше коде. В редком случае, когда вы хотите узнать строку шаблона формата, это также возможно:

    String osFormat = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
            FormatStyle.SHORT, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.getDefault());

Первый аргумент getLocalizedDateTimePattern - это стиль формата даты. Второй стиль времени.