Подтвердить что ты не робот

В JSF - Получение локали клиента (для отображения времени в часовом поясе браузера)

Я пишу webapp в JSF 2.0, который отображает Timestamps как часть информации для пользователя. Я хотел бы, чтобы пользователь видел метки времени, локализованные в их местоположении (язык браузера).

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

Я попытался получить локаль с помощью этих методов:

Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();

или

Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();

Оба вернули языковой стандарт сервера.

Затем я использую объект locale с SimpleDateFormat для печати временных меток.

Я использую правильный API?
Я где-то читал, что вам нужно использовать код на стороне клиента (Javascript), чтобы получить часовой пояс браузера. Это верно? Как вы это сделаете?

Спасибо 'n' Advance.

UPDATE найдено этот (jsTimezoneDetect) код JavaScript. Но я все еще не уверен, как перевести часовой пояс на Java Locale Object

4b9b3361

Ответ 1

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

В случае часового пояса он не имеет ничего общего с интернационализацией и локализацией, т.е. в США существует несколько разных часовых поясов. Существует два подхода, которые вы можете использовать здесь:

  • Сохранять информацию о часовом поясе в профиле пользователя (если таковая имеется). Это самый простой способ и позволяет использовать встроенный тег <f:convertDateTime>.

  • Получить информацию о часовом поясе из веб-браузера. Вы можете получить его через запрос Ajax, как в примере с Беном. Технически вы также можете использовать тег <f:convertDateTime> здесь.

  • Вы можете отправить отметки времени в формате UTC в каком-то общем, независимом от языка (или инвариантном, если хотите) формате, проанализировать его на стороне клиента для создания объекта даты и формата JavaScript для языка с Globalize.

Ниже приводятся некоторые примеры, но позвольте мне сначала что-то объяснить.

Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();

Этот будет предоставит вам веб-браузер (но не часовой пояс, так как это не). Он действительно прочитает содержимое заголовка HTTP-Accept-Language и выберет наилучший язык. Если он не работает для вас, убедитесь, что вы правильно настроили поддерживаемые локали в своем faces-config.xml. По наилучшему возможному языку я понимаю, что он попытается использовать наиболее предпочтительный пользовательский язык (если это поддерживается вашим приложением), а затем второе и так далее. Если ни один из локалей не поддерживается, он будет возвращаться к вашему стандарту Locals по умолчанию (опять же, faces-config.xml должен иметь этот параметр) или к языку по умолчанию сервера, если этот параметр отсутствует (или, по крайней мере, я так думаю, он добр имеет смысл).

Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();

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

BTW. FacesContext.getCurrentInstance().getExternalContext().getRequestLocales() предоставит вам Iterator, чтобы вы могли вручную перебирать список локалей в заголовке Accept-Language. Это просто, чтобы вы знали, вы, вероятно, не должны его использовать (UIViewRoot действительно достаточно).

Теперь предположим, что у вас есть bean с профилем пользователя и методом, который даст вам часовой пояс. Этот метод лучше, чем вызов Ajax, в том смысле, что может произойти, что два разных часовых пояса имеют одинаковое смещение по UTC, но переключают летнее время на другую дату (другими словами, некоторые временные метки будут напечатаны неправильно). Во всяком случае, в таком случае вы можете отформатировать свою метку времени (дата также исходит от некоторого bean):

<h:outputText value="#{someBean.timestamp}">
  <f:convertDateTime type="both" dateStyle="default" timeStyle="default" timeZone="#{userProfile.timeZone}" />
</h:outputtext>

Теперь позвольте мне объяснить атрибуты:

  • тип - что показывать, как означает дата и время
  • dateStyle - стиль даты (из коротких, средних, длинных, полных, по умолчанию). Вы действительно должны использовать default здесь, так как это будет использовать самый правильный формат для каждого Locale
  • timeStyle - похоже на стиль даты, но для временной части
  • timeZone - принимает либо смещение UTC (поэтому вам не нужно ничего конвертировать), либо имя часового пояса (т.е. America/Los_Angeles).

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

Объединять его с Ajax (см. ответ Ben) было бы достаточно просто (я думаю).

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

// 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, глобализация имеет только короткие ( "f" ) и длинные ( "F" ) форматы даты и времени. Поэтому я решил использовать короткий.
Также имейте в виду, что глобализация культур разделяется дефисом, а не подчеркиванием, поэтому вам нужно "fr-CA", а не "fr_CA", например.
Пожалуйста, дайте мне знать, если вы хотите использовать этот метод и нуждаетесь в более конкретном примере.

Ответ 2

Преемник. Вот что я сделал:

В JSF добавлено скрытое поле ввода, поэтому я могу отправить значения JavaScript на сервер:

<h:form prependId="false">
    <h:inputText id="timezone_holder" value="#{bean.timezone}" styleClass="hide">
        <f:ajax listener="#{bean.timezoneChangedListener}"></f:ajax>
    </h:inputText>
</h:form>

Используя плагин выше, я запустил код JavaScript, который получил смещение браузера.

$(document).ready(function() {
    var timezone = jstz.determine_timezone();

    $("#timezone_holder").val(timezone.offset());
    $("#timezone_holder").change();
});

При изменении ввода часового пояса (инициированного кодом javascript выше) я запускаю этот код в eventListener:

String strFromJavaScript = getTimezone();
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
                .getRequest();
Locale browserLocale = request.getLocale();
TimeZone tz = TimeZone.getTimeZone("GMT" + strFromJavaScript);

// set time zone
SimpleDateFormat formatter = new SimpleDateFormat("MMM d, yyyy, HH:mm", browserLocale);
formatter.setTimeZone(tz);

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

Ответ 3

Вы можете попробовать jsTimezoneDetect для определения часового пояса на стороне клиента и отправки на сервер.

UPDATE:, чтобы получить пользовательский язык, вы можете попробовать следующее:

HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
Locale locale = request.getLocale();

Возвращает объект "Перечисление локалей", указывающий при уменьшении начиная с предпочтительной локали, локали, которые приемлемый для клиента на основе заголовка Accept-Language. Если клиентский запрос не предоставляет заголовок Accept-Language, этот метод возвращает перечисление, содержащее один язык, локаль по умолчанию для сервера.

Ответ 4

Другой вариант - создать куки файл на Javascript, который будет выполняться, когда домашняя страница будет готова. После этого cookie будет существовать при каждом последующем запросе и будет доступен

Ваш Javascript может использовать jQuery и jsTimezoneDetect

    $(document).ready(function() {  
        setTimezoneCookie();
    });

    function setTimezoneCookie() {

        var timezone = jstz.determine().name();

        if (null == getCookie("timezoneCookie")) {
        document.cookie = "timezoneCookie=" + timezone;
        }
    }

    function getCookie(cookieName) {
        var cookieValue = document.cookie;
        var cookieStart = cookieValue.indexOf(" " + cookieName + "=");
        if (cookieStart == -1) {
            cookieStart = cookieValue.indexOf(cookieName + "=");
        }
        if (cookieStart == -1) {
            cookieValue = null;
        } else {
            cookieStart = cookieValue.indexOf("=", cookieStart) + 1;
            var cookieEnd = cookieValue.indexOf(";", cookieStart);
            if (cookieEnd == -1) {
                cookieEnd = cookieValue.length;
            }
            cookieValue = unescape(cookieValue.substring(cookieStart, cookieEnd));
        }
        return cookieValue;
    }

Затем ваш Facelet будет использовать значение cookie, если оно существует:

<h:outputText value="#{bean.time}">
   <f:convertDateTime
       dateStyle="full"
       timeStyle="full"
       type="both"
       timeZone="#{cookie.timezoneCookie.value}">
   </f:convertDateTime>
</h:outputText>

Ответ 5

Если вам нужно отображать отметки времени с местным временем пользователя, вам не нужен объект Locale (вам нужно добавить смещение часов часов в GMT + 0), Y Вам необходимо отправить значение timezone.offset() (из примера в ссылке) на сервер (вы можете сделать это, используя сообщение сервлета с параметром)

а затем добавьте это смещение к объекту даты, созданному на вашем сервере (установите для своей локали на сервере GMT ​​+ 00)

таким образом вы создадите отметки времени с правильным временем пользователя, зарегистрированного в вашем веб-приложении.

(что я сделал сам...)

Ответ 6

Вы также можете использовать его прямо в коде JSF:

<script type="text/javascript">
        $(document).ready(function () {
            var timezone = jstz.determine_timezone();
            $("#timezone_holder").val(timezone.name()); //use TimeZone name instead of offset
            $("#timezone_holder").change();
        });
</script>

Затем вы можете повторно использовать timezonename в конвертере JSF:

<f:convertDateTime pattern="dd.MM.yyyy HH:mm" timeZone="#{bean.timezone}" />