我如何获得本地化的date模式string?
使用DateFormat的实例格式化和parsingJava Date(或Calendar)类是非常容易的,也就是说,我可以将当前date格式化为如下所示的短本地化date:
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); String today = formatter.format(new Date());
我的问题是:我需要获得这个本地化的模式string(即像"MM/dd/yy"
)。 这应该是一个微不足道的任务,但我找不到提供者…
对于SimpleDateFormat ,您可以调用toLocalizedPattern()
编辑:
对于Java 8用户:
Java 8 Date Time API与Joda-time类似。 为了获得一个本地化的模式,我们可以使用DateTimeFormatter类
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
请注意,当您在LocalDate上调用toString()时,将以ISO-8601格式获取date
请注意,Java 8中的Date Time API受Joda Time的启发,大多数解决scheme都可以基于与时间有关的问题。
对于那些仍然使用Java 7和更旧的版本:
你可以使用这样的东西:
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); String pattern = ((SimpleDateFormat)formatter).toPattern(); String localPattern = ((SimpleDateFormat)formatter).toLocalizedPattern();
由于从getDateInstance()
返回的DateFormat
是SimpleDateFormat
实例。 这两个方法实际上也应该在DateFormat中,因为这样做不那么黑客,但他们现在不是。
可能很奇怪,我正在回答我自己的问题,但我相信,我可以在图片上添加一些东西。
ICU的实施
显然,Java 8给了你很多,但也有其他的东西: ICU4J 。 这实际上是Calendar
, DateFormat
和SimpleDateFormat
等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
- 25美分硬币
- 年
- YEAR_ABBR_QUARTER
- YEAR_QUARTER
- YEAR_ABBR_MONTH
- YEAR_MONTH
- YEAR_NUM_MONTH
- YEAR_ABBR_MONTH_DAY
- YEAR_NUM_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
- 月日
- NUM_MONTH_DAY
- ABBR_MONTH_WEEKDAY_DAY
- MONTH_WEEKDAY_DAY
- NUM_MONTH_WEEKDAY_DAY
- 天
- ABBR_WEEKDAY
- WEEKDAY
- 小时
- HOUR24
- HOUR_MINUTE
- HOUR_MINUTE_SECOND
- HOUR24_MINUTE
- HOUR24_MINUTE_SECOND
- HOUR_TZ
- HOUR_GENERIC_TZ
- HOUR_MINUTE_TZ
- HOUR_MINUTE_GENERIC_TZ
- 分钟
- MINUTE_SECOND
- 第二
- ABBR_UTC_TZ
- ABBR_SPECIFIC_TZ
- SPECIFIC_TZ
- ABBR_GENERIC_TZ
- GENERIC_TZ
- LOCATION_TZ
当然,还有不less。 它们的好处是这些模式实际上是string(就像在java.lang.String
),也就是说,如果使用英文模式"MM/d"
,则会返回特定于语言环境的模式。 在某些angular落案例中,这可能是有用的。 通常你只会使用DateFormat
实例,而不会关心模式本身。
特定于语言环境的模式与本地化模式
问题的意图是获得本地化,而不是特定于地区的模式。 有什么不同?
从理论上讲, toPattern()
会给你locale特定的模式(取决于你用来实例化(Simple)DateFormat
Locale
)。 也就是说,无论你放置什么目标语言/国家,你都会得到由y
, M
, d
, h
, H
, M
等符号组成的模式。
另一方面, toLocalizedPattern()
应该返回本地化的模式,这是适合最终用户阅读和理解的东西。 例如,德语中(默认)date模式将是:
- toPattern():dd.MM.yyyy
- toLocalizedPattern():tt.MM.jjjj(day = Tag,month = Monat,year = Jahr)
问题的意图是:“如何find可以作为date/时间格式的暗示的本地化模式”。 也就是说,我们有一个date字段,用户可以填写使用特定于语言环境的模式,但是我想以本地化的forms显示格式提示。
可悲的是,到目前为止没有好的解决办法。 我之前在这篇文章中提到的ICU部分工作。 这是因为,ICU使用的数据来自CLDR ,不幸的是部分翻译/部分正确。 如果是我母亲的话,在写作的时候,既没有模式,也没有他们的本地化forms被正确翻译。 每次我纠正他们,我都会被其他人没有必要住在波兰,也不会说波兰语。
这个故事的寓意:不完全依靠CLDR。 你仍然需要有当地的审计师/语言评论员。
您可以在Java 8中使用DateTimeFormatterBuilder 。以下示例仅返回本地化date模式,例如"dMyyyy"
。
String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern( FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.GERMANY); // or whatever Locale
以下代码将为您提供区域设置的模式:
final String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern(); System.out.println(pattern1);
Java 8提供了一些有用的function,用于处理和格式化/分析date和时间,包括处理区域设置。 这里是一个简要的介绍。
基本模式
在最简单的情况下格式化/parsing一个date,你可以使用下面的代码和一个String模式:
DateTimeFormatter.ofPattern("MM/dd/yyyy")
这个标准然后将这个与date对象直接用于格式化:
return LocalDate.now().format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
然后使用工厂模式parsingdate:
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("MM/dd/yyyy"));
该模式本身有大量的选项,将涵盖大部分的用例,可以在这里的javadoc位置find完整的概要。
语言环境
包含语言环境相当简单,对于默认语言环境,您可以将以下选项应用于上面显示的格式/parsing选项:
DateTimeFormatter.ofLocalizedDate(dateStyle);
上面的'dateStyle'是一个FormatStyle选项枚举,用于表示使用DateTimeFormatter
处理本地化date的完整,长期,中期和短期版本。 使用FormatStyle你也有以下select:
DateTimeFormatter.ofLocalizedTime(timeStyle); DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle); DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle, timeStyle);
最后一个选项允许您为date和时间指定一个不同的FormatStyle 。 如果您没有使用默认的Locale,则可以使用.withLocale选项来调整每个Localized方法的返回值,例如
DateTimeFormatter.ofLocalizedTime(timeStyle).withLocale(Locale.ENGLISH);
或者,ofPattern也有一个重载的版本来指定语言环境
DateTimeFormatter.ofPattern("MM/dd/yyyy",Locale.ENGLISH);
我需要更多!
DateTimeFormatter将满足大部分的用例,但它是build立在为构build器的用户提供大量选项的DateTimeFormatterBuilder上构build的。 使用DateTimeFormatter
开始,如果您需要这些广泛的格式化function回落到生成器。
因为它只是你所追求的语言环境信息 ,所以我认为你需要做的是findJVM(OpenJDK或Harmony)实际使用的文件作为整个Locale
的input,并找出如何parsing它。 或者只是在网上使用另一个来源(当然有一个列表)。 这将节省那些可怜的翻译。
请在下面的代码中find接受语言环境实例的代码,并返回特定于语言环境的数据格式/模式。
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; }
你可以尝试像这样:
LocalDate fromCustomPattern = LocalDate.parse("20.01.2014", DateTimeFormatter.ofPattern("MM/dd/yy"))
林不知道你想要什么,但…
SimpleDateFormat示例:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy"); Date date = sdf.parse("12/31/10"); String str = sdf.format(new Date());