如何从Locale获取当前时间和时区?

Ale*_*ila 15 java time timezone locale

我有这个奇怪的问题,当我创建一个带语言环境的日历时,TimeZone只是恢复到本地日历

public void start(Locale locale){
    String s = locale.getDisplayName(); 
    System.err.println(s);
    Calendar c = new GregorianCalendar(locale);
    System.err.println(c.getTimeZone());
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

 español (Argentina)
 sun.util.calendar.ZoneInfo[id="Europe/Bucharest", //etc more useless date here....
Run Code Online (Sandbox Code Playgroud)

如何从特定区域获得适当的时间?

Paw*_*yda 41

简短的回答:你做不到.

答案很长:没有"适合当地的时区"这样的事情.这只是因为有少数国家拥有多个时区(例如美国).时区是一个不同的概念.

无论如何,您正在寻求解决您的问题.我猜你正在编写一个Web应用程序,你发现时区正在恢复到服务器默认值.这是典型的情况.双方Locale.getDefault()TimeZone.getDefault()会返回服务器的相关信息.JVM无法知道"正确"的时区.所以你对此能做些什么?

  1. 您可以将时区信息添加到用户配置文件(如果有的话),或创建时区组合框(以便用户可以在运行时切换).然后,您可以为DateFormat实例分配适当的对象,它将自动转换时区.
  2. 您可以通过JavaScript Date Object的getTimezoneOffset()函数从客户端读取当前时区偏移量,并以某种方式(AJAX)将其发送到服务器.此方法的问题在于有多个具有该偏移的时区,并且所选时区可能不适合其他日期.当然,您可以通过在时间更改日期周围轮询数据来猜测时区,但这可能不是您想要做的.
  3. 您可以将未格式化的时间发送到客户端(例如,以ISO 8601日期时间格式或与UTC相关的时期Unix时间),并为您提供GlobalizeDojo格式的日期和时间.

在这三种可能的选择中,我总是选择数字1.通过将时区信息添加到用户个人资料中,您可以确定他/她的首选时区是什么,无论他们当前的网络浏览器等等.请记住,一些用户可能希望在访问其他国家时使用您的应用程序...

  • 还有另一种可能性,例如,如果您的网站列出了餐馆的营业时间。在这种情况下,访客会期望营业时间为餐厅所在地的时区。 (2认同)

Bas*_*que 7

语言环境和时区是正交问题

Locale

ALocale代表一对:

  • 一种人类语言,例如法语、英语或中文。
  • 一组文化规范,用于决定诸如大小写、缩写、元素顺序(如日期中的日-月-年)等格式问题,以及使用 COMMA 与 FULL STOP 作为小数分隔符等问题。

Locale不是地域。虽然 aLocale可能使用国家或地区作为表示文化规范的方式,但这并不意味着用户位于特定的地理区域。例如,一位来自魁北克的工程师在日本东京举行的一次会议上将使用的区域设置为 ,Locale.CANADA_FRENCH但她的时区可能是Asia/Tokyo她旅行期间的时区。

ZoneId

一个时区ZoneId代表过去,现在的历史和未来变化的偏移,从-UTC使用由特定地区的人们。偏移量只是 UTC 使用的本初子午线之前或之后的几个小时-分钟-秒数。世界各地的政治家都表现出频繁重新定义时区和更改其管辖范围使用的偏移量的倾向。事实上,那些采用夏令时 (DST) 的愚蠢地区每年更改两次偏移量,大约每六个月一次。

? 因此,不,您不能仅从给定的语言环境获取当前时间或时区。


当我使用区域设置创建日历时,时区只是恢复到本地

您正在使用现在遗留的糟糕的日期时间类,由 JSR 310 定义的现代java.time类取代。

要获取 UTC 中的当前时刻(零时分秒的偏移量),请使用Instant. AnInstant根据定义始终采用 UTC。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
Run Code Online (Sandbox Code Playgroud)

如果您想要特定时区中的当前时刻,请指定ZoneId以获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current moment as seen in the wall-clock time used by the people of a particular region.
Run Code Online (Sandbox Code Playgroud)

至于知道要申请的时区,正如我上面所说,您必须:

您可以通过调用 获取已知时区的列表ZoneId.getAvailableZoneIds

Calendar c = new GregorianCalendar( locale ) ;

您可能会对这个GregorianCalendar采用 a 的构造函数感到困惑,这是可以Locale理解的。

这个构造函数是在遗留日期时间类中发现的许多糟糕和不正确的设计决策之一。坦率地说,这些遗留类非常糟糕,它们是由不了解日期时间处理的复杂性和微妙之处的人设计的。Sun、Oracle 和 JCP 社区出于充分的理由决定java.time取代它们。

Locale在生成表示日期时间对象的值以显示给用户的文本时,它与时区相交。ALocale指定用于翻译月份名称、星期几名称等的人类语言。并Locale指定了决定问题的文化规范,例如缩写月份或星期几(名称是否大写?是否附加了 FULL STOP?)、订购日、月和年等方面。