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

时间:2012-05-13 10:04:06

标签: 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());
}

这是输出:

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

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

2 个答案:

答案 0 :(得分:37)

简短的回答:你不能。

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

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

  1. 您可以将时区信息添加到用户配置文件(如果有的话),或创建时区组合框(以便用户可以在运行时切换)。然后,您可以将适当的对象分配给DateFormat实例,它将自动转换时区。
  2. 您可以通过JavaScript Date对象的getTimezoneOffset()函数从客户端读取 当前 时区偏移量,并以某种方式(AJAX)将其发送到服务器。此方法的问题在于有多个具有该偏移的时区,并且所选时区可能不适合其他日期。当然,您可以通过在时间更改日期周围轮询数据来猜测时区,但这可能不是您想要做的。
  3. 您可以将未格式化的时间发送给客户端(例如写为ISO 8601 date-time format或与Unix time of the epoch相关的UTC)并具有GlobalizeDojo格式的日期和你的时间。
  4. 在这三种可能的选择中,我总是选择数字1.通过将时区信息添加到用户个人资料中,您可以确定他/她的首选时区是什么,无论他们当前的网络浏览器等等。请保持请记住,有些用户可能希望在访问其他国家时使用您的应用程序......

答案 1 :(得分:1)

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

Locale

Locale代表一对:

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

Locale不是地理)。尽管Locale可以使用国家或地区作为代表文化规范的方式,但这并不意味着用户在特定的地理区域内。例如,魁北克的一位工程师在日本东京的一次会议上将使用Locale.CANADA_FRENCH的语言环境,但在旅行期间她的时区可能是Asia/Tokyo

ZoneId

time zoneZoneId代表特定地区人民使用的offset-from-UTC的过去,现在和将来的历史。偏移量仅是UTC使用的本初子午线之前或之后数小时-数分钟-秒。世界各地的政界人士都表现出对重新定义时区并更改其辖区使用的偏移量的兴趣。实际上,那些采用“夏令时”(DST)愚蠢做法的地区每年都会偏移两次,大约六个月一次。

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


  

当我创建一个具有区域设置的日历时,TimeZone会还原为本地区域

您使用的是可怕的日期时间类,而现在这些类是由JSR 310定义的现代 java.time 类所取代的。

要获取当前的UTC时间(零时分秒),请使用Instant。根据定义,Instant始终使用UTC。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

如果要在特定时区中使用当前时刻,请指定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.

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

您可以通过致电ZoneId.getAvailableZoneIds获取已知时区的列表。

  

Calendar c = new GregorianCalendar( locale ) ;

您可能对此GregorianCalendar的构造方法感到困惑,但认为它是Locale

此构造函数是在遗留日期时间类中发现的很多错误的设计决策之一。直白地说,这些遗留类非常糟糕,由不了解日期时间处理的复杂性和微妙性的人设计。 Sun, Oracle, and the JCP community decided有充分理由将其替换为 java.time

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