在Java中解析日期时间字符串是否需要Locale?
- 在什么条件下我需要用
Locale
Java解析日期时间字符串? - 语言环境与时区有什么关系?
有时我会在“问题与解答”中看到需要解析语言的地方。但是在其他语言中,没有提及语言环境。
回答:
地区和时区无关
就日期时间处理而言,语言环境和时区是相互独立的正交问题。
人类语言,例如阿拉伯语,法语,波斯语。星期几名称,月份名称和序号指示符的文本。例如……是
Monday
还是Lundi
?通常使用成语来安排组成日期时间值的字符串表示形式的文本和数字。例如......在短短的形式,是
month-date-year
,date-month-
year或
year-month-date
?从长远来看,星期几是第一位吗?月份名称是否具有首字母大写还是全部小写?缩写是否带有“ FULLSTOP”(句号)字符?
时间UTC(GMT)是一个地区的人们在墙上使用的时间
之间的时差(以分钟为单位),这是世界调节时钟和时间的主要时间标准。
偏移量的更改历史,当前应用的定义偏移量的规则(包括夏令时(DST)等调整)以及已确认的变更计划即将在不久的将来出现。
因此,您可以混合匹配区域设置和时区。以下是一些示例。
- 一位在印度浦那参加会议的法国人需要查看印度会议时间的安排,但宁愿将“ Monday”读成他的母语“ Lundi”。
- 法国语言环境
- 印度时区
- 一位在西雅图工作的巴西工程师希望收看来自Turku Finland的现场网络研讨会。她需要知道何时将网络浏览器指向网络研讨会。在调整为西雅图时区后,她需要知道芬兰的开始时间,但必须使用她的母语葡萄牙语来显示巴西语言环境。
- __用于演示的 Locale(“ pt”,“ BR”) (用于生成文本表示)
- 芬兰的预定开始时间必须从调整
Europe/Helsinki
为America/Los_Angeles
(西雅图时区)。
- 冰岛的一家报纸可能会将在俄罗斯发生的一件事件报道为两个日期时间,莫斯科时区,为清楚起见添加了UTC时区。但是本文将使用冰岛语作为文本,包括星期几。
- 莫斯科时区和冰岛语言环境
- UTC时区和冰岛语言环境
解析/生成日期时间值的文本表示的字符串时,仅在两种情况下使用语言环境:
- 星期几的名称和/或月份的名称(或序号,但最好避免使用)
- 软编码的本地化格式
在第一种情况下,如果您的字符串包含“星期一” /“隆迪”或“三月” /“火星”之类的单词,则将使用语言环境来翻译这些字符串。
在第二种情况下,如果您没有显式的格式化模式,则使用语言环境来了解星期几,日期,月名,年等各部分的预期顺序。 。例如,说英语的美国人说“
10月11日”,而说法语的加拿大人则使用相反的顺序“
10月11日”。所谓的软编码,是指DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL
)相对于硬编码的格式,例如DateTimeFormatter.ofPattern("yyyy
MM dd,
EEE")
那么什么时候不需要区域设置?如果您输入的字符串全为数字,例如“ 2015-01-23”,并且您正在将该格式硬编码为“ yyyy-MM-dd”…
String input = "2015-01-23";DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd")
…那么语言环境实际上是无关紧要的。您没有要翻译的单词,也没有“星期一”或“隆迪”。并且不要求使用本地化的格式化程序,该格式化程序需要一个语言环境才能知道日期是在月份之前还是之后,以及其他此类详细信息。
请注意,在这种情况下,您仍然可以指定语言环境。实际上,我建议您 (以及时区)的 。
回答:
那么,为什么您在StackOverflow上看到如此多与日期时间相关的问答,而没有任何语言环境?因为如果省略,则JVM的当前默认语言环境将自动且无提示地应用。
因此,如果您在设置为美国语言环境的JVM上运行带有英文文本的字符串,则没有问题。但是不建议这种对隐式语言环境的依赖。如果 在运行时
调用任何应用程序的任何线程中的任何代码Locale.setDefault
,并且会影响该JVM中的所有其他代码。然后,您的代码将引发异常。最好养成明确指定期望/期望区域设置的习惯。
时区的建议相同。如果省略,则将自动且无提示地应用JMV的当前默认时区。同样, 在运行时
任何应用程序的任何线程中的任何代码都可以调用TimeZone.setDefault
,并影响该JVM中的所有其他代码。然后,您的代码将引发Exception或行为异常。
运行时的意外更改应该足以养成始终指定区域设置和时区的习惯。但是另一个好处是,它还可以使您的代码自我记录。同样,在编程时自觉指定语言环境和时区可能会提醒您有关错误或未经证实的假设。
示例场景
想象一个魁北克的商人。她与土耳其的一位客户确认了他的交货时间,该交货时间为中午。因此,她使用壁挂时间在土耳其创建了一个可以接受交货的对象。
ZoneId zoneIdIstanbul = ZoneId.of( "Europe/Istanbul" );ZonedDateTime zdtIstanbul = ZonedDateTime.of( 2015, 10, 11, 12, 30, 00, 0, zoneIdIstanbul ); // Half-past noon in Turkey.
为了方便客户,她使用土耳其语和习俗来设置文本格式。她定义了一个格式化程序对象,以处理日期时间值的文本表示形式的生成。我们还可以在生成文本表示时为要应用的格式程序分配一个时区。但是ZonedDateTime对象已经分配了一个时区,因此格式化程序将在该时区启动。
Locale locale_tr_TR = new Locale( "tr", "TR" );DateTimeFormatter formatter_tr_TR = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale_tr_TR );
String outputTurkish = formatter_tr_TR.format( zdtIstanbul );
我们的业务人员知道客户使用芬兰的物流协调员,因此她使用芬兰语打印相同的日期时间值。因此,我们在土耳其时区设置了芬兰语区域。
Locale locale_fi_FI = new Locale( "fi", "FI" );DateTimeFormatter formatter_fi_FI = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale_fi_FI );
String outputFinnish = formatter_fi_FI.format( zdtIstanbul );
就她自己而言,她需要在自己的固定时间内提供预期交货的字符串,以便可以设置警报以提醒她检查是否成功完成。她母语是法语,而不是土耳其语。
因此,下一个代码是不同的,因为我们需要调整时区 和
语言环境。在时间轴上的同一时刻,即预期交付的日期时间,但在文本中的表示方式有所不同。请注意,这次是如何withZone
在链的末尾添加一个额外的调用,以创建一个格式化程序,在此我们指定时区调整以覆盖ZonedDateTime对象的已分配区域。
Locale locale_fr_CA = Locale.CANADA_FRENCH;ZoneId zoneId_Montréal = ZoneId.of( "America/Montreal" );
DateTimeFormatter formatter_fr_CA_Adjusted = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale_fr_CA ).withZone( zoneId_Montréal );
String outputQuébec = formatter_fr_CA_Adjusted.format( zdtIstanbul );
最后,为了我们的讲英语的StackOverflow.com读者,我们来做一个英文版本。但是请注意,我们回收了魁北克格式器,保留了已设置的时区,但将语言环境替换为美国的语言环境。(从技术上讲,不是回收,而是说。不可变对象的使用意味着将基于旧对象的值实例化一个新对象。)
Locale locale_en_US = Locale.US;DateTimeFormatter formatter_US_Unadjusted = formatter_fr_CA_Adjusted.withLocale( locale_en_US );
String output_US_Unadjusted = formatter_US_Unadjusted.format( zdtIstanbul );
让我们看看这些值的输出。转储到控制台。
首先,我们toString
在ZonedDateTime
对象上隐式调用该方法。默认情况下,此方法使用ISO
8601定义的标准格式之一。但是java.time通过在方括号中添加时区名称来扩展该格式[Europe/Istanbul]
。交换数据时,请使用这些明确的标准格式,而不要使用任何更人性化的格式。
System.out.println( "zdtIstanbul : " + zdtIstanbul );System.out.println( "outputTurkish : " + outputTurkish );
System.out.println( "outputFinnish : " + outputFinnish );
System.out.println( "outputQuébec : " + outputQuébec );
System.out.println( "output_US_Unadjusted : " + output_US_Unadjusted );
输出信息告诉我们,土耳其的午餐时间对我们魁北克的女性来说意味着5:30 AM的警报。
zdtIstanbul : 2015-10-11T12:30+03:00[Europe/Istanbul]outputTurkish : 11 Ekim 2015 Pazar 12:30:00 EEST
outputFinnish : sunnuntai, 11. lokakuuta 2015 12.30.00 EEST
outputQuébec : dimanche 11 octobre 2015 5 h 30 EDT
output_US_Unadjusted : Sunday, October 11, 2015 5:30:00 AM EDT
以上是 在Java中解析日期时间字符串是否需要Locale? 的全部内容, 来源链接: utcz.com/qa/400305.html