您可能应该使用内置格式标记而不是 SimpleDateFormat。您的问题意味着您想向国际用户显示日期和时间,在这种情况下,您应该真正使用用户的本地格式(您知道,它们往往会有所不同)。
就时区而言,它与国际化和本地化无关,即美国有几个不同的时区。您可以在这里使用两种方法:
在用户配置文件中存储时区信息(如果有的话)。这是最简单的方法,允许您使用内置的<f:convertDateTime> 标签。
从 Web 浏览器获取时区信息。您可以像 Ben 的示例一样通过 Ajax 请求获取它。从技术上讲,您也可以在此处使用<f:convertDateTime> 标签。
1234563 /p>
下面会有一些例子,但让我先解释一下。
Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
这将为您提供网络浏览器的区域设置(但不是时区,因为这与区域设置不相关)。它实际上会读取 HTTP Accept-Language 标头的内容并选择最佳的语言环境。如果它不适合您,请确保您在 faces-config.xml 中正确设置了支持的语言环境。通过最好的语言环境,我知道它将尝试使用用户最喜欢的语言环境(如果您的应用程序支持),然后是第二好的,依此类推。如果不支持任何语言环境,它将回退到您的应用程序的默认语言环境(同样,faces-config.xml 必须具有此设置)或者如果缺少此设置(或者至少我认为是这样,它会返回到服务器的默认语言环境)有道理)。
Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
这将为您提供来自 Accept-Language 标头的顶级语言环境。请检查您的网络浏览器设置 - 几乎无法为您提供服务器区域设置,除非它们与您的网络浏览器完全相同。当且仅当 JVM 不支持任何 Web 浏览器的 Locale(这似乎不太可能)时,它才能为您提供服务器的默认值。
顺便说一句。 FacesContext.getCurrentInstance().getExternalContext().getRequestLocales() 将为您提供迭代器,以便您可以手动迭代 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 - 日期样式(短、中、长、完整、默认)。您真的应该在这里使用默认值,因为这将为每个区域设置使用最合适的格式
- timeStyle - 类似于日期样式,但用于时间部分
- timeZone - 采用 UTC 偏移量(因此您无需转换任何内容)或时区名称(即 America/Los_Angeles)。
标签默认使用当前视图语言环境,所以你不必担心这部分,特别是如果你正确设置了语言环境支持。
将它与 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”。
如果您想使用该方法并需要更具体的示例,请告诉我。