gpt4 book ai didi

java - 在 Java 中解析日期时间字符串是否需要 `Locale`?

转载 作者:行者123 更新时间:2023-12-02 01:21:47 36 4
gpt4 key购买 nike

  • 什么情况下需要 Locale 用于解析 Java 中的日期时间字符串?
  • Locale 与 time zone 有什么关系? ?

  • 有时我会看到问题与解答,其中需要语言环境来解决解析问题。然而,在其他地方却没有提到 Locale。

    最佳答案

    区域设置和时区无关

    语言环境和时区是分开的,orthogonal关于日期时间处理的问题。

  • 语言环境
  • 语言 人类语言,如Arabic , French , Farsi .星期名称、月份名称和 ordinal indicators 的文本.比如……是不是MondayLundi ?
  • 文化 排列构成日期时间值的字符串表示形式的文本和数字片段时常用的习语。例如……简而言之,是 month-date-year , date-month-year , 或 year-month-date ?在长格式中,一周中的哪一天在前?月份名称是否有首字母大写或全部小写?缩写是否有 FULL STOP (PERIOD)性格与否?
  • 时区
  • 偏移 wall-time之间的小时数和分钟数差异来自 UTC 的人在一个区域使用( GMT ),世界调节时钟和时间的主要时间标准。
  • 异常 对偏移量所做更改的历史记录,当前应用的定义偏移量的规则,包括诸如 Daylight Saving Time (DST) 之类的调整,并确认了在不久的将来进行更改的计划。

  • 因此,您可以混合搭配区域设置和时区。下面是一些例子。
  • 一位在印度浦那参加 session 的法国人需要在印度的墙上时间查看 session 时间表,但更愿意将“星期一”读为“伦迪”,他的母语是法语。
  • 法语语言环境
  • 印度时区
  • 一位在西雅图工作的巴西工程师想要观看来自芬兰图尔库的网络研讨会直播。她需要知道何时将网络浏览器指向网络研讨会。在调整到西雅图时区后,她需要知道芬兰的开始时间,但要使用巴西语言环境以她的母语葡萄牙语显示。
  • Locale( "pt", "BR") 用于表示(用于生成文本表示)
  • 在芬兰的预定开始时间必须从 Europe/Helsinki 调整至 America/Los_Angeles (西雅图时区)。
  • 冰岛的一家报纸可能会将俄罗斯发生的事件报告为两个日期时间,莫斯科时区和为清楚起见添加 UTC 时区。但文章将使用冰岛语作为包括星期几在内的文本。
  • 莫斯科时区和冰岛语言环境
  • UTC 时区和冰岛语言环境

  • 在解析/生成作为日期时间值的文本表示的字符串时,Locale 仅在两种情况下使用:
  • 星期几和/或月份名称(或序数指标,但最好避免这些)
  • 软编码、本地化格式

  • 在第一种情况下,如果您的字符串包含诸如“Monday”/“Lundi”或“March”/“Mars”之类的词,则使用语言环境来翻译这些字符串。

    在第二种情况下,如果您没有明确的格式化模式,则使用 Locale 来了解星期几、日期、月份名称、年份等部分的预期顺序.例如,说英语的美国人说“October 11”,而说法语的加拿大人则使用相反的顺序“11 octobre”。通过软编码,我们的意思是类似 DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ) 与像 DateTimeFormatter.ofPattern("yyyy MM dd, EEE") 这样的硬编码格式相比

    那么什么时候不需要 Locale 呢?如果您有一个包含所有数字的输入字符串,例如“2015-01-23”,并且您将格式硬编码为“yyyy-MM-dd”……
    String input = "2015-01-23";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd")

    ……那么 Locale 实际上是无关紧要的。你没有要翻译的词,没有“星期一”或“伦迪”。并且不要求使用需要语言环境才能知道日期是在月份之前还是之后的本地化格式化程序,以及其他此类详细信息。

    请注意,在这种情况下,您仍然可以指定区域设置。确实,我建议你做一个 总是指定 Locale 的习惯 (还有时区)。

    隐式语言环境和时区

    那么为什么你会在 StackOverflow 上看到这么多没有任何语言环境的与日期时间相关的问答?因为如果省略,JVM 的当前默认语言环境将自动且静默地应用。

    因此,如果您在设置为美国语言环境的 JVM 上运行带有英文文本的字符串,那么没问题。但是不推荐这种对隐式语言环境的依赖。如果在运行时调用任何应用程序的任何线程中的任何代码 Locale.setDefault ,并影响该 JVM 中的所有其他代码。然后你的代码抛出一个异常。最好养成明确指定预期/所需语言环境的习惯。

    对时区的相同建议。如果省略,则会自动且无提示地应用 JMV 当前的默认时区。同样,运行时任何应用程序的任何线程中的任何代码都可以调用 TimeZone.setDefault ,并影响该 JVM 中的所有其他代码。然后您的代码抛出异常或行为异常。

    Surprise-changes-at-runtime 应该足以让我们养成始终指定语言环境和时区的习惯。但另一个好处是它还使您的代码自记录。此外,在编程时有意识地指定区域设置和时区可能会提醒您注意不正确或未经证实的假设。

    示例场景

    想象一下魁北克的一位商人。她与土耳其的一位客户确认他的交货时间为中午时间。因此,她在土耳其使用挂墙时间创建了一个对象,在那里可以接受交付。
    ZoneId zoneIdIstanbul = ZoneId.of( "Europe/Istanbul" );
    ZonedDateTime zdtIstanbul = ZonedDateTime.of( 2015, 10, 11, 12, 30, 00, 0, zoneIdIstanbul ); // Half-past noon in Turkey.

    为了客户的方便,她使用 Turkish language 格式化文本和习俗。她定义了一个格式化程序对象来处理日期时间值的文本表示的生成。我们还可以在生成文本表示时为要应用的格式化程序分配一个时区。但是 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 );

    我们的业务人员知道客户在芬兰使用物流协调员,因此她在 Finnish 中打印了相同的日期时间值。 .所以我们有一个 Turkey time zone带有芬兰语环境。
    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 );

    最后,为了我们的 English - 说 StackOverflow.com 的读者,让我们做一个英文版本。但请注意,我们回收了 Québec 格式化程序,保留了已经设置的时区,但将区域设置替换为美国的区域设置。 (技术上不是回收,而是可以这么说。使用 immutable objects 意味着使用基于旧对象的值实例化新对象。)
    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 发出警报。

    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 - 在 Java 中解析日期时间字符串是否需要 `Locale`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32162108/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com