SimpleDateFormat and locale based format string
我正在尝试基于给定的语言环境以不同的方式在Java中格式化日期。 例如,我希望英国用户看到"2009年11月1日"(由"MMM d,yyyy"格式化)和挪威用户看到"1. nov.2009"("d.MMM.yyyy")。
如果我将语言环境添加到SimpleDateFormat构造函数中,那么月份部分可以正常工作,但其余部分呢?
我希望我可以将与locales配对的格式字符串添加到SimpleDateFormat,但我找不到任何方法来执行此操作。 是否可以或者我需要让我的代码检查语言环境并添加相应的格式字符串?
使用DateFormat.getDateInstance(int style,Locale locale)而不是使用
1 2 | SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE dd MMM yyyy", Locale.ENGLISH); String formatted = dateFormat.format(the_date_you_want_here); |
使用style + locale:DateFormat.getDateInstance(int style,Locale locale)
查看http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html
运行以下示例以查看差异:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import java.text.DateFormat; import java.util.Date; import java.util.Locale; public class DateFormatDemoSO { public static void main(String args[]) { int style = DateFormat.MEDIUM; //Also try with style = DateFormat.FULL and DateFormat.SHORT Date date = new Date(); DateFormat df; df = DateFormat.getDateInstance(style, Locale.UK); System.out.println("United Kingdom:" + df.format(date)); df = DateFormat.getDateInstance(style, Locale.US); System.out.println("USA:" + df.format(date)); df = DateFormat.getDateInstance(style, Locale.FRANCE); System.out.println("France:" + df.format(date)); df = DateFormat.getDateInstance(style, Locale.ITALY); System.out.println("Italy:" + df.format(date)); df = DateFormat.getDateInstance(style, Locale.JAPAN); System.out.println("Japan:" + df.format(date)); } } |
输出:
1 2 3 4 5 | United Kingdom: 25-Sep-2017 USA: Sep 25, 2017 France: 25 sept. 2017 Italy: 25-set-2017 Japan: 2017/09/25 |
TL;博士
1 2 3 4 | LocalDate.now().format( DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ) .withLocale( new Locale("no" ,"NO" ) ) ) |
麻烦的
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是"昨天"。
1 2 | ZoneId z = ZoneId.of("America/Montreal" ); LocalDate today = LocalDate.now( z ); |
使用
要进行本地化,请指定:
-
FormatStyle 确定字符串应该多长或缩写。 -
Locale 确定(a)用于翻译日期名称,月份名称等的人类语言,以及(b)决定缩写,大小写,标点符号等问题的文化规范。
例:
1 2 3 |
走向另一个方向,您可以解析本地化的字符串。
1 | LocalDate ld = LocalDate.parse( input , f ); |
请注意,区域设置和时区是完全正交的问题。您可以用日语或以印地语提供的奥克兰新西兰时刻呈现蒙特利尔时刻。
另一个例子:将
1 2 3 4 5 |
细读格式
下面是一些示例代码,用于在多个语言环境中仔细阅读多种格式的结果,并自动进行本地化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ); List < Locale > locales = new ArrayList <>( 3 ); locales.add( Locale.CANADA_FRENCH ); locales.add( new Locale("no" ,"NO" ) ); locales.add( Locale.US ); // Or use all locales (almost 800 of them, for about 120K text results). // Locale[] locales = Locale.getAvailableLocales(); // All known locales. Almost 800 of them. for ( Locale locale : locales ) { System.out.println("------| LOCALE:" + locale +" —" + locale.getDisplayName() +" |----------------------------------" + System.lineSeparator() ); for ( FormatStyle style : EnumSet.allOf( FormatStyle.class ) ) { DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( style ).withLocale( locale ); String output = ld.format( f ); System.out.println( output ); } System.out.println("" ); } System.out.println("? fin ?" + System.lineSeparator() ); |
输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ------| LOCALE: fr_CA — French (Canada) |---------------------------------- mardi 23 janvier 2018 23 janvier 2018 23 janv. 2018 18-01-23 ------| LOCALE: no_NO — Norwegian (Norway) |---------------------------------- tirsdag 23. januar 2018 23. januar 2018 23. jan. 2018 23.01.2018 ------| LOCALE: en_US — English (United States) |---------------------------------- Tuesday, January 23, 2018 January 23, 2018 Jan 23, 2018 1/23/18 ? fin ? |
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要
从哪里获取java.time类?
-
Java SE 8,Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小功能和修复。
-
Java SE 6和Java SE 7
- 许多java.time功能都被反向移植到Java 6&amp; 7在ThreeTen-Backport。
-
Android的
- 更高版本的Android捆绑java.time类的实现。
- 对于早期的Android,ThreeTenABP项目采用ThreeTen-Backport(如上所述)。请参见如何使用ThreeTenABP ....
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。您可以在这里找到一些有用的类,例如
日期字符串的本地化:
基于redsonic的帖子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | private String localizeDate(String inputdate, Locale locale) { Date date = new Date(); SimpleDateFormat dateFormatCN = new SimpleDateFormat("dd-MMM-yyyy", locale); SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy"); try { date = dateFormat.parse(inputdate); } catch (ParseException e) { log.warn("Input date was not correct. Can not localize it."); return inputdate; } return dateFormatCN.format(date); } String localizedDate = localizeDate("05-Sep-2013", new Locale("zh","CN")); |
将像05-九月-2013
这将根据用户的当前区域设置显示日期:
要返回日期和时间:
1 2 3 4 5 6 | import java.text.DateFormat; import java.util.Date; Date date = new Date(); DateFormat df = DateFormat.getDateTimeInstance(); String myDate = df.format(date); |
1969年12月31日下午7:00:02
要仅返回日期,请使用:
1 |
1969年12月31日
给定日期的Java 8样式
1 2 3 4 | LocalDate today = LocalDate.of(1982, Month.AUGUST, 31); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.ENGLISH))); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.FRENCH))); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.JAPANESE))); |
1 |
Java8
1 2 | import java.time.format.DateTimeFormatter; myDate.format(DateTimeFormatter.ofPattern("dd-MMM-YYYY",new Locale("ar"))) |