【问题标题】:How to get Date pattern from Timezone of Locale in Java如何从 Java 中的语言环境时区获取日期模式
【发布时间】:2011-12-01 06:20:27
【问题描述】:

我有一个时区和用户的区域设置。现在我想得到日期模式。

例如:用户的时区 PST 和 Locale US,我期望的模式是“MM/dd/yyyy”,如果用户的时区是 IST 和 Locale India,那么我期望的模式是“dd/MM/yyyy”

如何获得?

注意:我想获取模式而不是实际日期,以便我可以在其他地方使用它。

【问题讨论】:

  • 为什么不使用“这个其他地方”中的语言环境,而不仅仅是模式?
  • 嗨 Petal Ivanov,实际上,我想将模式传递给 Javascript,所以我不能使用语言环境。

标签: java date timezone locale


【解决方案1】:

Locale 转换为日期/时间格式的逻辑隐藏在java.text.SimpleDateFormat#SimpleDateFormat 构造函数中,恰好在sun.util.resources.LocaleData#getDateFormatData 中。此方法提供ResourceBundle,然后根据选择的样式查询特定模式。

换句话说 - 不幸的是,JDK 似乎没有提供 API/SPI 来访问原始格式。我的建议是一直使用Locale 并将其传递给格式化/解析方法。

【讨论】:

  • +1 用于将语言环境传递给您自己的格式化方法,最终灵活的解决方案
【解决方案2】:

您真的需要 TZ 作为日期模式吗?通常的方法是在语言环境(或 locale_country)的本地化属性文件中使用数据模式。我觉得够了。

【讨论】:

  • 我不需要 TZ 作为日期模式。但总的来说,这就是我手中的东西(用户的时区详细信息)。 “通常的方法是在区域设置(或 locale_country)的本地化属性文件中使用数据模式” - 这是否意味着,最好的方法是在国家级别维护日期模式(并将其保存在数据库或文件系统中)?
  • 是的。无法从 http 请求中检索 TZ,因此您只知道客户端的语言环境/国家/地区。另一种方法是询问用户 TZ 并将其与其余用户信息一起保存在数据库中。
【解决方案3】:

java.time

现代解决方案使用 java.time 类,该类在几年前取代了可怕的遗留类,例如 SimpleDateFormat。具体替换为DateTimeFormatter

跳过格式化模式,让java.time自动本地化

你问:

我有一个时区和用户的区域设置。现在我想获取日期模式。

不需要实际获取特定语言环境使用的格式模式。

DateTimeFormatter 上的 .ofLocalized… 方法返回一个格式化程序对象,该对象可以自动本地化表示日期时间对象值的文本。所以你不需要看模式,只需要生成文本结果。

FormatStyle 对象控制文本的长度或缩写。 Locale 决定了用于本地化的人类语言和文化规范。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ; 

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = 
        DateTimeFormatter
        .ofLocalizedDateTime( FormatStyle.FULL )
        .withLocale( locale ) 
;
String output = zdt.format( f ) ;

转储到控制台。

System.out.println( zdt.toInstant().toString() ) ;  // Adjust to UTC.
System.out.println( zdt.toString() ) ;              // Generate text in standard ISO 8601 format extended wisely to append the name of the time zone in square brackets.
System.out.println( output ) ;                      // Automatically formatted content.

看到这个code run live at IdeOne.com

2020-07-13T23:26:40.554180Z

2020-07-14T08:26:40.554180+09:00[亚洲/东京]

mardi 14 juillet 2020 à 08 h 26 min 40 s heure normale du Japon


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

从哪里获取 java.time 类?

【讨论】:

    【解决方案4】:

    听起来您想要在 DateFormat 上使用 static getInstance methods。它们采用整数常量作为样式(短、长等),并且可以选择不同的区域设置(而不是 JVM 的默认设置)。

    【讨论】:

      【解决方案5】:

      你可以使用Interface Map

      k 将是语言环境 v 将是一个带有日期模式的字符串

      【讨论】:

        【解决方案6】:

        如果您使用 Joda Time(如果您有任何选择,为什么不选择?它几乎被捆绑到 JDK 1.7 中)您可以执行以下操作:

        String patternForStyleAndLocale = org.joda.time.format.DateTimeFormat.patternForStyle("S-", locale);
        

        不幸的是,这仅给出了两位数的年份。一种解决方法是:

        if (!org.apache.commons.lang.StringUtils.contains(patternForStyleAndLocale, "yyyy"))
        {
            // The default Joda pattern only has a two digit year for US and Europe, China etc - but we want four digit years
            patternForStyleAndLocale = StringUtils.replace(patternForStyleAndLocale, "yy", "yyyy");
        }
        

        您可以考虑将它们缓存在 ConcurrentHashMap<Locale, String> 中。

        像这样将数字日期作为预本地化模式获取的好处是,它以后不需要任何进一步的本地化,如果您使用以下模式就会这样做:

        "dd MMM yyyy" // UK: "25 Dec 2010" FRANCE: "25 déc. 2010" etc..
        

        但是...我刚刚从您后来的评论中注意到,您希望将模式传递给 JavaScript - 这可能会变得非常困难,因为 JS 使用与 Java 不同的模式格式(例如 ISO 日期是"yyyy-MM-dd" 在 Java 中和 "yy-mm-dd" 在 JS 中)。我没有尝试解决这个问题,但我可能会在 JS 或 Java 中使用一些字符串映射来简单地从 Java 模式映射到 JS。当然,您必须提前了解每种语言可能遇到的每种模式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-03
          • 2010-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-10
          相关资源
          最近更新 更多