Почему Java читает настройки по умолчанию из системы - PullRequest
15 голосов
/ 18 апреля 2010

Java считывает информацию о локали, часовом поясе и кодировке (и, возможно, больше) из системы, в которой она установлена.

Это часто приносит неприятные сюрпризы (принес мне один только вчера). Предположим, что на ваших серверах разработки и производства установлена ​​TimeZone GMT + 2. Затем вы развертываете на производственном сервере с GMT. 2-часовая смена может быть нелегко наблюдать сразу. И хотя вы можете передавать TimeZone в свои календари, API могут создавать экземпляры календарей (или дат) с использованием часового пояса по умолчанию.

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

Итак, почему у Java нет собственных значений по умолчанию - UTF-8, GMT, en_US (да, я нахожусь не в локали en-en_US, но иметь ее по умолчанию хорошо) При необходимости приложения могут читать системные настройки через некоторый API.

Таким образом, программы будут более предсказуемыми.

Итак, в чем причина этого решения?

Ответы [ 6 ]

8 голосов
/ 18 апреля 2010

Это не уникально для Java. Многие системы по умолчанию используют системный часовой пояс. В конце концов, что еще они могут сделать?

Часовые пояса - острые проблемы, особенно когда приложение должно работать с несколькими часовыми поясами. Вот почему такие сайты помещают все в UTC.

Что касается вашей ситуации, это трудно комментировать, потому что описание довольно расплывчато, но, похоже, это ваша ошибка. Если вы сохранили дату (без часового пояса) в одном месте в GMT + 2, а затем загрузили ее в другом в GMT, значит, вы сделали что-то не так.

7 голосов
/ 18 апреля 2010

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

Если вы хотите повлиять на настройки по умолчанию, обычно есть системные свойства, которые вы можете установить при запуске приложения, например

java -Duser.timezone=Europe/London

и т.д.

Лично я думаю, что проблема не в выборе по умолчанию, а в том, что он так легко используется. Даже Joda Time (который я люблю во многих, многих отношениях) делает слишком простым случайное использование часового пояса по умолчанию. То же самое относится и к кодировкам и т. Д.

РЕДАКТИРОВАТЬ: Другой вариант - использовать метод main (или другой модуль ранней инициализации), который вызывает

TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));

и аналогично для других системных настроек по умолчанию.

3 голосов
/ 18 апреля 2010

Я считаю, это потому, что это не так удивительно для большего количества людей.

Большинство программ (в том числе на других языках) используют часовой пояс локального развертывания.Это было так целую вечность.Если вы хотите что-то еще, вы можете переопределить это.Представьте, если бы это было иначе: у нас был бы такой же вопрос в обратном направлении, но задаваемый большим количеством людей.

(Используйте UTC для отметок времени, когда вы не можете просто сместить-из-эпоха.)

2 голосов
/ 18 апреля 2010

Я могу себе представить эту необходимость всякий раз, когда вы разрабатываете корпоративное (веб) приложение, работающее на сервере, доступ к которому должен получить каждый человек в мире, но это не требуется для обычных настольных приложений. Постарайтесь также думать в их контексте. Вы не хотите, чтобы пользователи клиентских приложений, не подозревающие в программировании, конфигурировали свои системные настройки по умолчанию только потому, что у Java есть свои собственные настройки по умолчанию. Вы, как разработчик корпоративных (веб-приложений) приложений, должны сами это учитывать.

0 голосов
/ 17 февраля 2018

ТЛ; др

«Почему» не имеет значения, поскольку фреймворки и API, обеспечивающие такие значения по умолчанию, являются общими для всех.

Всегда передавайте ZoneId & Locale явно, даже если это необязательно.

LocalDate.now( ZoneId.of( "Africa/Tunis" ) )

... и ...

DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
    .withLocale( Locale.JAPAN )

Укажите необязательные аргументы

Мало того, что текущий часовой пояс JVM по умолчанию и локаль находятся вне вашего контроля как программиста (исходя из хост-ОС или из параметров запуска JVM), они могут измениться в любой момент во время выполнения. Любой код в любом потоке любого приложения в JVM может изменить либо зону по умолчанию, либо локаль.

Лучше всегда явно указывайте желаемую / ожидаемую зону или локаль , передавая необязательные аргументы, а не неявно полагайтесь на текущее значение по умолчанию JVM.

Часовой пояс

Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париж Франция - новый день, а еще «вчера» в Монреаль Квебек .

Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент, поэтому ваши результаты могут отличаться. Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента.

Укажите собственное имя часового пояса в формате continent/region, например America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте 3-4-буквенное сокращение, такое как EST или IST, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента. Если опущено, текущее значение по умолчанию JVM применяется неявно. Лучше быть явным, поскольку значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Locale

Класс DateTimeFormatter может автоматически локализоваться при генерации строки, представляющей значение даты-времени.

Instant instant = Instant.now();  // Current moment in UTC with a resolution of up to nanoseconds.
ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime zdt = instant.atZone( z );  // Adjust from UTC to a specific time zone. Same moment, different wall-clock time.

Для локализации укажите:

  • FormatStyle для определения длины или сокращения строки.
  • Locale для определения (а) человеческого языка для перевода названия дня, названия месяца и т. Д., И (б) культурных норм, решающих вопросы сокращения, капитализации, пунктуации, разделители и тому подобное.

Пример: * 1 077 *

ZoneId z = ZoneId.of( "Pacific/Auckland" ); 
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

Locale l = Locale.CANADA_FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );

Примечания

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

Допустим, на ваших серверах разработки и производства настроен TimeZone GMT + 2.

Вообще говоря, серверы должны быть настроены на UTC. Но, как обсуждалось выше, никогда не полагайтесь на это. Передайте желаемый / ожидаемый часовой пояс в качестве аргументов, даже если вы хотите использовать UTC.

2-часовая смена может быть нелегко наблюдать сразу.

Теперь вы можете выполнять тестирование проще с java.time , передавая альтернативные реализации класса Clock. Этот класс сам по себе предоставляет альтернативные варианты поведения, такие как установка фиксированного времени или установка часов на много часов / минут впереди или позади истинного времени.

Скорее всего, вам потребуется переписать некоторый код, чтобы сообщить о зоне, локали или кодировке с помощью какого-либо внедрение-зависимости . Это может быть так же просто, как передача аргументов в раздел кода.

И хотя вы можете передавать TimeZone в свои календари, API могут создавать экземпляры календарей (или дат) с использованием часового пояса по умолчанию.

Кажется, что очень распространенная проблема, что программисты игнорируют проблему часового пояса и локали. Вероятно, из-за невежества, а не из-за лени.

Здесь нет волшебной пули, кроме:

  • Обучите своих программистов обработке даты и времени, локализации и кодированию символов .
  • Установите стандарт для вашей команды, настаивая на том, чтобы зона, локаль и кодировка символов всегда были явными. Если требуется значение по умолчанию, сделайте явный вызов, чтобы получить значение по умолчанию.

Я согласен с мнением, связанным с вашим Вопросом. Фреймворки и API никогда не должны предоставлять значения по умолчанию для часового пояса, локали и кодировки символов , по моему скромному мнению. Полагаясь на такие настройки по умолчанию, не задумываясь программистами, это источник некоторых самых неприятных неуловимых ошибок времени выполнения. Но, c’est la vie , нам приходится иметь дело с реальностью как есть.

0 голосов
/ 18 апреля 2010

Если вы развертываете вещи на производственном сервере, настроенном на GMT, разумное поведение по умолчанию - использовать GMT по умолчанию. Предполагается, что Java является языком программирования и средой, а не целой операционной системой в системе. Поддержание собственного набора настроек по умолчанию не является частью работы стандартной библиотеки.

И рассмотрим альтернативную ситуацию: если Java поддерживала свои собственные настройки для таких вещей, как часовые пояса, все, кто хотел использовать разные настройки (например, все, кто не в GMT, вероятно ~ 90% пользователей компьютеров), кто хотел использовать Java Программа должна была бы вручную изменить часовой пояс Java. Это было бы еще сложнее для людей, которые используют системы, сочетающие Java с каким-либо другим языком, потому что на одном компьютере у вас будут разные программы, использующие разные (и, вероятно, несовместимые) настройки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...