Вы, вероятно, должны использовать встроенный тег форматирования вместо SimpleDateFormat.Ваш вопрос подразумевает, что вы хотите показывать дату и время международному пользователю, и в этом случае вам действительно следует использовать локальный формат пользователя (они, как вы знаете, имеют тенденцию к различию).
В случае часового пояса он имеетНичего общего с интернационализацией и локализацией, то есть в США есть несколько часовых поясов.Здесь вы можете использовать два подхода:
Сохранять информацию о часовом поясе в профиле пользователя (если он у вас есть).Это самый простой способ, позволяющий использовать встроенный тег <f:convertDateTime>
.
Получение информации о часовом поясе из веб-браузера.Вы можете получить его через запрос Ajax, как в примере с Беном.Технически вы также можете использовать тег <f:convertDateTime>
здесь.
Вы можете отправлять временные метки в формате UTC в каком-либо общепринятом, не зависящем от локали (или инвариантном, если хотите) формате, проанализируйте его вна стороне клиента для создания объекта даты и формата JavaScript для локали с помощью Globalize .
Ниже будут приведены некоторые примеры, но позвольте мне сначала кое-что объяснить.
Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
Это будет отображать языковой стандарт веб-браузера (но не часовой пояс, поскольку не языковой стандарт).Он фактически прочитает содержимое заголовка HTTP Accept-Language и выберет наилучшую возможную локаль.Если это не работает для вас, пожалуйста, убедитесь, что вы правильно установили поддерживаемые локали в вашем faces-config.xml
.Под лучшим возможным языком я понимаю, что он будет пытаться использовать наиболее предпочтительный язык пользователя (если это поддерживается вашим приложением), затем второе место и так далее.Если ни один из языковых стандартов не поддерживается, он будет возвращаться к стандартным языкам вашего приложения (опять же, faces-config.xml
должен иметь этот параметр) или к стандартному языку сервера, если этот параметр отсутствует (или, по крайней мере, я так думаю, этоиз имеет смысл).
Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
Этот даст вам верхнюю локаль из заголовка Accept-Language.Пожалуйста, проверьте настройки вашего веб-браузера - почти невозможно , чтобы он мог предоставить вам языковой стандарт сервера, если они не совпадают с настройками вашего веб-браузера.Это может дать вам настройки сервера по умолчанию тогда и только тогда, когда ни одна из локалей веб-браузера не поддерживается JVM (что кажется немного маловероятным).
Кстати.FacesContext.getCurrentInstance().getExternalContext().getRequestLocales()
даст вам Итератор, чтобы вы могли вручную перебирать список Locales в заголовке Accept-Language.Это просто для того, чтобы вы знали, что вы, вероятно, не должны его использовать (UIViewRoot действительно достаточно).
Теперь предположим, что у вас есть некоторый компонент с профилем пользователя и метод, который даст вам часовой пояс.Этот метод лучше, чем Ajax-вызов, в том смысле, что два разных часовых пояса могут иметь одинаковое смещение UTC, но переключать летнее время на другую дату (другими словами, некоторые временные метки будут напечатаны неправильно).В любом случае, в таком случае вы можете отформатировать свою метку времени следующим образом (дата также получена из некоторого компонента):
<h:outputText value="#{someBean.timestamp}">
<f:convertDateTime type="both" dateStyle="default" timeStyle="default" timeZone="#{userProfile.timeZone}" />
</h:outputtext>
Теперь позвольте мне объяснить атрибуты:
- type - что показывать, оба означают дату и время
- dateStyle - стиль даты (из короткого, среднего, длинного, полного, по умолчанию).Вы должны действительно использовать значение по умолчанию здесь, так как это будет использовать наиболее подходящий формат для каждого Locale
- timeStyle - аналогично стилю даты, но для временной части
- timeZone - принимает смещение UTC (так что вы нене нужно ничего преобразовывать) или имя часового пояса (например, America / Los_Angeles).
По умолчанию тег будет использовать текущее представление Locale, поэтому вам не нужно беспокоиться об этой части, особенно есливы правильно настроили поддержку Locale.
Объединить ее с Ajax (см. ответ Бена) было бы достаточно легко (я думаю).
Я также упомянул, что вы можете записывать инвариантные даты, анализировать ихна стороне клиента, а затем отформатируйте их с помощью Globalize.Предполагая, что вы уже проанализировали дату (это зависит от представления, которое вы хотите использовать, поэтому я пропущу эту часть), это можно сделать так:
// you also have to assign the culture based on UIViewRoot locale and send it out with JavaScript
Globalize.culture(theLocale);
var formattedDateTime = Globalize.format(parsedDateTime, "f"); // this will use short date time format
В отличие от Java, у Globalize есть только короткие ("f") и длинные ("F") форматы даты и времени. Поэтому я решил использовать короткий.
Также имейте в виду, что культуры Globalize разделяются дефисом, а не подчеркиванием, поэтому вам нужен, например, «fr-CA», а не «fr_CA».
Пожалуйста, дайте мне знать, если вы хотите использовать этот метод и вам нужен более конкретный пример.