如何获取本地化的日期模式字符串?

时间:2011-01-04 14:11:19

标签: java datetime localization internationalization

使用DateFormat的实例格式化和解析Java Date(或Calendar)类非常容易,即我可以将当​​前日期格式化为短的本地化日期,如下所示:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String today = formatter.format(new Date());

我的问题是:我需要获取这个本地化的模式字符串(例如"MM/dd/yy")。这应该是一项微不足道的任务,但我找不到提供者......

10 个答案:

答案 0 :(得分:36)

对于SimpleDateFormat,您拨打toLocalizedPattern()

修改

对于Java 8用户:

Java 8 Date Time API与Joda-time类似。要获得本地化模式,我们可以使用类 DateTimeFormatter

DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);

请注意,当您在LocalDate上调用toString()时,您将获得ISO-8601格式的日期

请注意,Java 8中的Date Time API受Joda Time的启发,大多数解决方案可以基于与时间相关的问题。

答案 1 :(得分:30)

对于那些仍在使用Java 7及更早版本的人:

您可以使用以下内容:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String pattern       = ((SimpleDateFormat)formatter).toPattern();
String localPattern  = ((SimpleDateFormat)formatter).toLocalizedPattern();

由于从DateFormat返回的getDateInstance()SimpleDateFormat的实例。 这两种方法实际上也应该在DateFormat中,因为它不那么hacky,但它们目前不是。

答案 2 :(得分:20)

我可能很奇怪,我正在回答我自己的问题,但我相信,我可以在图片中添加一些内容。

ICU实施

显然,Java 8给了你很多东西,但还有其他东西:ICU4J。这实际上是CalendarDateFormatSimpleDateFormat之类的Java原始实现的来源,仅举几例。 因此,ICU SimpleDateFormat也包含toPattern()toLocalizedPattern()等方法也不足为奇。你可以在这里看到它们:

DateFormat fmt = DateFormat.getPatternInstance(
        DateFormat.YEAR_MONTH,
        Locale.forLanguageTag("pl-PL"));

if (fmt instanceof SimpleDateFormat) {
    SimpleDateFormat sfmt = (SimpleDateFormat) fmt;
    String pattern = sfmt.toPattern();
    String localizedPattern = sfmt.toLocalizedPattern();
    System.out.println(pattern);
    System.out.println(localizedPattern);
}

ICU增强功能

这不是什么新鲜事,但我真正想指出的是:

DateFormat.getPatternInstance(String pattern, Locale locale);

这是一种可以返回一大堆特定于语言环境的模式的方法,例如:

  • ABBR_QUARTER
  • YEAR
  • YEAR_ABBR_QUARTER
  • YEAR_QUARTER
  • YEAR_ABBR_MONTH
  • YEAR_MONTH
  • YEAR_NUM_MONTH
  • YEAR_ABBR_MONTH_DAY
  • YEAR_NUM_MONTH_DAY
  • YEAR_MONTH_DAY
  • YEAR_ABBR_MONTH_WEEKDAY_DAY
  • YEAR_MONTH_WEEKDAY_DAY
  • YEAR_NUM_MONTH_WEEKDAY_DAY
  • ABBR_MONTH
  • NUM_MONTH
  • ABBR_STANDALONE_MONTH
  • STANDALONE_MONTH
  • ABBR_MONTH_DAY
  • MONTH_DAY
  • NUM_MONTH_DAY
  • ABBR_MONTH_WEEKDAY_DAY
  • MONTH_WEEKDAY_DAY
  • NUM_MONTH_WEEKDAY_DAY
  • ABBR_WEEKDAY
  • WEEKDAY
  • HOUR
  • HOUR24
  • HOUR_MINUTE
  • HOUR_MINUTE_SECOND
  • HOUR24_MINUTE
  • HOUR24_MINUTE_SECOND
  • HOUR_TZ
  • HOUR_GENERIC_TZ
  • HOUR_MINUTE_TZ
  • HOUR_MINUTE_GENERIC_TZ
  • MINUTE
  • MINUTE_SECOND
  • SECOND
  • ABBR_UTC_TZ
  • ABBR_SPECIFIC_TZ
  • SPECIFIC_TZ
  • ABBR_GENERIC_TZ
  • GENERIC_TZ
  • LOCATION_TZ

当然,有很多。它们的优点是,这些模式实际上是字符串(如java.lang.String中所示),即如果使用英语模式"MM/d",那么您将获得特定于语言环境的模式作为回报。它可能在某些极端情况下有用。通常你只需使用DateFormat实例,并且不关心模式本身。

特定于区域设置的模式与已本地化的模式

问题意图是获得本地化,而不是特定于语言环境的模式。有什么区别?

理论上,toPattern()将为您提供特定于语言环境的模式(取决于您用于实例化Locale的{​​{1}})。也就是说,无论您放置什么目标语言/国家/地区,您都会获得由(Simple)DateFormatyMd,{等符号组成的模式{1}},h

另一方面,H 应该返回本地化模式,这适合最终用户阅读和理解。例如,德语中间(默认)日期模式将是:

  • toPattern():dd.MM.yyyy
  • toLocalizedPattern():tt.MM.jjjj(day = Tag,month = Monat,year = Jahr)

问题的意图是:"如何找到可以作为日期/时间格式是什么的提示的本地化模式"。也就是说,我们有一个日期字段,用户可以使用特定于语言环境的模式填写,但我想以本地化的形式显示格式提示。

可悲的是,到目前为止还没有很好的解决方案。我在本文前面提到的ICU部分有效。这是因为,ICU使用的数据来自CLDR,遗憾的是部分翻译/部分正确。在我母亲的舌头的情况下,在撰写本文时,无论是模式还是其本地化形式都没有被正确翻译。每当我纠正它们时,我都被其他人所支持,他们不必在波兰生活,也不会说波兰语......

这个故事的寓意:不完全依赖CLDR。您仍需要当地审核员/语言审核员。

答案 3 :(得分:11)

您可以在Java 8中使用DateTimeFormatterBuilder。以下示例仅返回本地化日期模式,例如"d.M.yyyy"

String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
  FormatStyle.SHORT, null, IsoChronology.INSTANCE, 
  Locale.GERMANY); // or whatever Locale

答案 4 :(得分:5)

以下代码将为您提供区域设置的模式:

final String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern();
System.out.println(pattern1);

答案 5 :(得分:4)

Java 8提供了一些开箱即用的有用功能,用于处理和格式化/解析日期和时间,包括处理语言环境。这是一个简短的介绍。

基本模式

在最简单的情况下,要格式化/解析日期,您将使用以下代码和String模式:

DateTimeFormatter.ofPattern("MM/dd/yyyy")

然后标准将这个与日期对象一起用于格式化:

return LocalDate.now().format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));

然后使用工厂模式解析日期:

return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("MM/dd/yyyy"));

模式本身有大量选项可以覆盖大多数用例,可以在javadoc位置here找到完整的纲要。

区域设置

包含Locale非常简单,对于默认语言环境,您可以使用以下选项,然后将这些选项应用于上面演示的格式/解析选项:

DateTimeFormatter.ofLocalizedDate(dateStyle);

上面的'dateStyle'是FormatStyle选项Enum,用于表示使用DateTimeFormatter时本地化日期的完整版,长版,中版和短版。使用FormatStyle您还可以选择以下选项:

DateTimeFormatter.ofLocalizedTime(timeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle, timeStyle);

最后一个选项允许您为日期和时间指定不同的FormatStyle。如果您不使用默认的Locale,则可以使用.withLocale选项调整每个Localized方法的返回值,例如

DateTimeFormatter.ofLocalizedTime(timeStyle).withLocale(Locale.ENGLISH);

或者,ofPattern也有一个重载版本来指定语言环境

DateTimeFormatter.ofPattern("MM/dd/yyyy",Locale.ENGLISH);

我需要更多!

DateTimeFormatter将满足大多数用例,但它建立在DateTimeFormatterBuilder上,为构建器的用户提供了大量选项。使用DateTimeFormatter开始,如果您需要这些广泛的格式化功能,请回退到构建器。

答案 6 :(得分:1)

请在下面的代码中找到接受语言环境实例并返回特定于语言环境的数据格式/模式。

 public static String getLocaleDatePattern(Locale locale) {
    // Validating if Locale instance is null
    if (locale == null || locale.getLanguage() == null) {
        return "MM/dd/yyyy";
    }
    // Fetching the locale specific date pattern
    String localeDatePattern = ((SimpleDateFormat) DateFormat.getDateInstance(
            DateFormat.SHORT, locale)).toPattern();
    // Validating if locale type is having language code for Chinese and country 
    // code for (Hong Kong) with Date Format as - yy'?'M'?'d'?'
    if (locale.toString().equalsIgnoreCase("zh_hk")) {
        // Expected application Date Format for Chinese (Hong Kong) locale type
        return "yyyy'MM'dd";
    }
    // Replacing all d|m|y OR Gy with dd|MM|yyyy as per the locale date pattern
    localeDatePattern = localeDatePattern.replaceAll("d{1,2}", "dd").replaceAll(
            "M{1,2}", "MM").replaceAll("y{1,4}|Gy", "yyyy");
    // Replacing all blank spaces in the locale date pattern
    localeDatePattern = localeDatePattern.replace(" ", "");
    // Validating the date pattern length to remove any extract characters
    if (localeDatePattern.length() > 10) {
        // Keeping the standard length as expected by the application
        localeDatePattern = localeDatePattern.substring(0, 10);
    }
    return localeDatePattern;
}

答案 7 :(得分:0)

由于它只是您所关注的语言环境信息,我认为您需要做的是找到JVM(OpenJDK或Harmony)实际用作整个文件的文件{ {1}}事情并弄清楚如何解析它。或者只是在网络上使用其他来源(肯定有一个列表)。这将拯救那些可怜的译员。

答案 8 :(得分:-2)

您可以尝试以下内容:

LocalDate fromCustomPattern = LocalDate.parse("20.01.2014", DateTimeFormatter.ofPattern("MM/dd/yy"))

答案 9 :(得分:-4)

我不确定你想要什么,但是......

SimpleDateFormat示例:

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");
Date date = sdf.parse("12/31/10");
String str = sdf.format(new Date());