ユーザーへの情報の一部としてタイムスタンプを表示するWebアプリをJSF2.0で作成しています。自分の場所(ブラウザーのロケール)にローカライズされたタイムスタンプをユーザーに表示してもらいたい。
これまでのところ、私が何をしたとしても、タイムスタンプは常にサーバーのタイムゾーンにローカライズされているように見えます。
私はこれらの方法でロケールを取得しようとしました:
Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
または
Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
どちらもサーバーのロケールを返しました。
次に、ロケールオブジェクトをSimpleDateFormat
とともに使用して、タイムスタンプを出力します。
正しいAPIを使用していますか?
ブラウザのタイムゾーンを取得するには、クライアント側のコード(Javascript)を使用する必要があることをどこかで読みました。あれは正しいですか?どうしますか?
'n'Advanceに感謝します。
[〜#〜] update [〜#〜]が見つかりました this (jsTimezoneDetect)JavaScriptコード。しかし、タイムゾーンをJava Locale
オブジェクトに変換する方法がまだわかりません
SimpleDateFormatの代わりに組み込みのフォーマットタグを使用する必要があります。あなたの質問は、国際ユーザーに日付と時刻を表示したいことを意味します。この場合、実際にはユーザーのローカル形式を使用する必要があります(それらは異なる傾向があります)。
タイムゾーンの場合、国際化とローカリゼーションとは関係ありません。つまり、米国にはいくつかの異なるタイムゾーンがあります。ここで使用できるアプローチは2つあります。
タイムゾーン情報をユーザープロファイルに保存します(ある場合)。これが最も簡単な方法であり、組み込みの_<f:convertDateTime>
_タグを使用できます。
Webブラウザからタイムゾーン情報を取得します。ベンの例のように、Ajaxリクエストを介して取得できます。技術的には、ここで_<f:convertDateTime>
_タグを使用することもできます。
タイムスタンプをUTCで、ロケールに依存しない一般的な(または必要に応じて不変の)形式で送信し、クライアント側で解析して、JavaScriptの日付オブジェクトとロケールの形式を Globalize で作成できます。
いくつかの例を次に示しますが、最初に何かを説明しましょう。
_Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
_
このwillは、Webブラウザのロケールを提供します(ただし、これはであるため、タイムゾーンは提供されません) notロケール関連)。実際にHTTPAccept-Languageヘッダーの内容を読み取り、可能な限り最適なロケールを選択します。それが機能しない場合は、_faces-config.xml
_でサポートされているロケールが正しく設定されていることを確認してください。可能な限り最良のロケールでは、ユーザーが最も好むロケール(アプリケーションでサポートされている場合)を使用し、次に2番目に良いロケールを使用しようとすることを理解しています。いずれのロケールもサポートされていない場合は、アプリケーションのデフォルトのロケールにフォールバックします(ここでも、_faces-config.xml
_にこの設定が必要です)。この設定がない場合は、サーバーのデフォルトのロケールにフォールバックします(または少なくともそう思います。それはちょっと理にかなっています)。
_Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
_
これにより、Accept-Languageヘッダーの最上位ロケールが表示されます。 Webブラウザの設定を確認してください-Webブラウザとまったく同じでない限り、サーバーのロケールを提供する方法はほとんどありません。 WebブラウザのロケールがJVMでサポートされていない場合にのみ、サーバーのデフォルトを提供できます(これは少しありそうもないようです)。
ところで。 FacesContext.getCurrentInstance().getExternalContext().getRequestLocales()
はイテレーターを提供するので、Accept-Languageヘッダーのロケールのリストを手動で繰り返すことができます。それはあなたに知らせるためだけです、あなたはおそらくそれを使うべきではありません(UIViewRootは本当に十分です)。
ここで、ユーザープロファイルとタイムゾーンを提供するメソッドを備えたBeanがあるとします。この方法は、2つの異なるタイムゾーンが同じUTCオフセットを持っているが、異なる日付で夏時間を切り替える可能性があるという意味で、Ajax呼び出しよりも優れています(つまり、一部のタイムスタンプが正しく印刷されません)。とにかく、このような場合は、タイムスタンプを次のようにフォーマットできます(日付も一部のBeanから取得されます)。
_<h:outputText value="#{someBean.timestamp}">
<f:convertDateTime type="both" dateStyle="default" timeStyle="default" timeZone="#{userProfile.timeZone}" />
</h:outputtext>
_
次に、属性について説明します。
タグはデフォルトで現在のビューロケールを使用するため、特にロケールサポートを正しく設定している場合は、この部分について心配する必要はありません。
それをAjax(Benの答えを参照)と組み合わせるのは簡単です(私は思います)。
また、不変の日付を書き出し、クライアント側で解析してから、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」が必要になることにも注意してください。
その方法を使用したい場合で、より具体的な例が必要な場合はお知らせください。
成功しました。これが私がしたことです:
JavaScript値をサーバーに送信できるように、JSFに非表示の入力フィールドを追加しました。
<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);
次に、日付をフォーマットする必要があるときはいつでも、上記で作成した日付フォーマッターを使用します。
jsTimezoneDetect を試して、クライアント側でタイムゾーンを検出し、サーバーに送信することをお勧めします。
UPDATE:ユーザーのロケールを取得するには、次のことを試してください。
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
Locale locale = request.getLocale();
Accept-Languageヘッダーに基づいてクライアントに受け入れられるロケールを、優先ロケールから降順で示すロケールオブジェクトの列挙を返します。クライアント要求がAccept-Languageヘッダーを提供しない場合、このメソッドは、サーバーのデフォルトロケールである1つのロケールを含む列挙型を返します。
別のオプションは、ホームページの準備ができたときに実行されるJavascript上にCookieを作成することです。その後、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;
}
フェイスレットは、Cookieが存在する場合、その値を使用します。
<h:outputText value="#{bean.time}">
<f:convertDateTime
dateStyle="full"
timeStyle="full"
type="both"
timeZone="#{cookie.timezoneCookie.value}">
</f:convertDateTime>
</h:outputText>
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>
次に、JSFコンバーターでtimezonenameを再利用できます。
<f:convertDateTime pattern="dd.MM.yyyy HH:mm" timeZone="#{bean.timezone}" />
必要なのがLocaleオブジェクトを必要としないユーザーの現地時間でタイムスタンプを表示することだけである場合(ユーザーの時間オフセットをGMT + 0時間に追加する必要があります)、Y timezone.offset()の値を送信する必要があります(リンクの例から)サーバーへ(パラメータ付きのサーブレット投稿を使用して実行できます)
次に、このオフセットをサーバー上に作成された日付オブジェクトに追加します(サーバー上のロケールをGMT + 00に設定します)
そうすれば、Webアプリにログインしているユーザーの正しい時刻でタイムスタンプを作成できます
(それは私が自分でしたことです...)