Locale和时间区是两个不同的问题
Locale
Locale
表示以下两个内容的组合:
- 人类语言,例如法语、英语或中文。
- 文化规范,用于决定格式设置问题,如首字母大写、缩写、日期中日月年元素的顺序以及使用逗号还是句点作为小数分隔符等。
Locale
与地理位置无关。虽然Locale
可能会使用国家或区域作为表示文化规范的一种方式,但这并不意味着用户实际上位于特定的地理区域。例如,参加在东京举办的会议的魁北克工程师将使用Locale.CANADA_FRENCH
,但她的时区可能在整个旅行期间为Asia/Tokyo
。
ZoneId
时间区 ZoneId
表示特定区域的人们使用的相对于UTC的偏移量过去、现在和未来的变化历史。偏移量仅是UTC使用的本初子午线之前或之后的小时数-分钟数-秒数。世界各地的政客经常重新定义其时区并更改其辖区使用的偏移量。实际上,那些采纳了夏令时(DST)愚蠢做法的地区每年大约六个月会更改其偏移量两次。
➥ 因此,您不能仅从给定的Locale
获取当前时间或时区。
当我使用locale创建日历时,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 和 JCP 社区决定 使用 java.time 取代它们,有很充分的理由。
在生成表示日期时间对象的值以供用户显示时,Locale
与时区相交。 Locale
指定在翻译月份名称、星期几名称等方面使用的人类语言。并且 Locale
指定了决定缩写月份或星期几(名称是否大写?是否附加 FULL STOP?),订购日、月和年以及其他此类方面的文化规范。