使用 SimpleDateFormat(string,locale) 的法语语言环境解析错误
Parsing error for French locale with SimpleDateFormat(string,locale)
我的 java 端有一段这样的代码:
private static DateFormat getHourFormatter(){
//DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(_locale);
Locale locale = Locale.FRENCH; //locale : "fr"
DateFormat hourFormatter = new SimpleDateFormat( "hh:mm a",locale); //hourFormatter: simpleDateFormat@103068 locale: "fr"
hourFormatter.setTimeZone( TimeZone.getTimeZone("GMT") );
return hourFormatter; //hourFormatter: SimpleDateFormat@103068
}
protected static boolean isHoursTimeStringValid( String hourDisplay ) {
try {
getHourFormatter().parse( hourDisplay ); //hourDisplay: "01:01 Matin"
return true;
} catch (ParseException e) { //e: "java.text.ParseException: Upparseable date "01:01 Matin"
return false;
}
}
如果我将语言环境值更改为美国,英语语言环境工作正常。
但对于法语语言环境,它抛出解析错误。
java.text.ParseException: Upparseable date "01:01 Matin"
我已将调试信息添加为注释行以便更好地理解
在不重写现有代码库的情况下,您仍可以为此特定目的引入 java.time
、现代 Java 日期和时间 API。它确实提供了法语的解决方案:
Map<Long, String> amPmText = new HashMap<>(4);
amPmText.put(0L, "Matin");
amPmText.put(1L, "Soir");
DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder().appendPattern("hh:mm ")
.appendText(ChronoField.AMPM_OF_DAY, amPmText)
.toFormatter(Locale.FRENCH);
System.out.println(LocalTime.parse("01:01 Matin", timeFormatter));
System.out.println(LocalTime.parse("10:59 Soir", timeFormatter));
这会打印
01:01
22:59
混合使用java.time
和过时的类
到目前为止,我们的代码库(旧的)是新旧日期和时间的有趣组合 API 使用。坦率地说,我们很少重写任何旧的和有效的代码,但我们总是使用现代 API 来编写新代码。
我强烈建议尽可能使用 java.time
。与它一起工作通常要好得多。一旦你开始使用它,我相信你会不想回去。
对于纯 SimpleDateFormat
解决方案,请参阅 。
当且仅当您只有两个可能的值(这里是 AM/PM),那么您可以用 SimpleDateFormat
这样做:
DateFormatSymbols dfs = DateFormatSymbols.getInstance(Locale.FRENCH);
dfs.setAmPmStrings(new String[] { "Matin", "Soir" });
SimpleDateFormat input = new SimpleDateFormat("hh:mm a", Locale.FRENCH);
input.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
input.setDateFormatSymbols(dfs);
Date parsed = input.parse("01:01 Matin");
// control of parsing
SimpleDateFormat output = new SimpleDateFormat("HH:mm");
output.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
System.out.println(output.format(parsed)); // 01:01 (24-hour-clock)
我在这里将时区设置为 GMT 以防止任何时区影响。如果需要,您可以偏离它(但需要小心)。
正如一些评论中提到的,我仍然不认为使用 AM/PM 字段真的适合英语以外的其他语言。例如,法语至少知道两个或更多值,例如 "nuit"(=night)或 "après-midi"(=afternoon)。但是对于旧的 API 或新的 java.time
-package(需要外部库,如 ICU4J 或 Time4J),这种方式是不可能的。
谢谢大家的回答。
正如我之前提到的,我无力更改代码库。
所以,我所做的是:
public void setBeginAMPM( String ampm ) {
if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.am" ))) {
_beginAMPM = "AM";
}
else if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.pm" ))) {
_beginAMPM = "PM";
}
else{
_beginAMPM = ampm;
}
}
public void setEndAMPM( String ampm ) {
if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.am" ))) {
_endAMPM = "AM";
}
else if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.pm" ))) {
_endAMPM = "PM";
}
else{
_endAMPM = ampm;
}
}
_locale 值我从操作 class 传递到从 class。如果它不是英语,它将进入 if 块之一,或者如果是英语,它将默认进入 else 块。根据本地值,它从属性文件中获取 AM/PM 值并相应地进行转换。
我只是将 AM/PM 值从其他特定于语言环境的语言修改为英语,因为 SimpleDateFormat() 仅支持英语。
你们可以称之为丑陋的 hack,但你猜怎么着,它正在解决我的目的。
我的 java 端有一段这样的代码:
private static DateFormat getHourFormatter(){
//DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(_locale);
Locale locale = Locale.FRENCH; //locale : "fr"
DateFormat hourFormatter = new SimpleDateFormat( "hh:mm a",locale); //hourFormatter: simpleDateFormat@103068 locale: "fr"
hourFormatter.setTimeZone( TimeZone.getTimeZone("GMT") );
return hourFormatter; //hourFormatter: SimpleDateFormat@103068
}
protected static boolean isHoursTimeStringValid( String hourDisplay ) {
try {
getHourFormatter().parse( hourDisplay ); //hourDisplay: "01:01 Matin"
return true;
} catch (ParseException e) { //e: "java.text.ParseException: Upparseable date "01:01 Matin"
return false;
}
}
如果我将语言环境值更改为美国,英语语言环境工作正常。
但对于法语语言环境,它抛出解析错误。
java.text.ParseException: Upparseable date "01:01 Matin"
我已将调试信息添加为注释行以便更好地理解
在不重写现有代码库的情况下,您仍可以为此特定目的引入 java.time
、现代 Java 日期和时间 API。它确实提供了法语的解决方案:
Map<Long, String> amPmText = new HashMap<>(4);
amPmText.put(0L, "Matin");
amPmText.put(1L, "Soir");
DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder().appendPattern("hh:mm ")
.appendText(ChronoField.AMPM_OF_DAY, amPmText)
.toFormatter(Locale.FRENCH);
System.out.println(LocalTime.parse("01:01 Matin", timeFormatter));
System.out.println(LocalTime.parse("10:59 Soir", timeFormatter));
这会打印
01:01
22:59
混合使用java.time
和过时的类
到目前为止,我们的代码库(旧的)是新旧日期和时间的有趣组合 API 使用。坦率地说,我们很少重写任何旧的和有效的代码,但我们总是使用现代 API 来编写新代码。
我强烈建议尽可能使用 java.time
。与它一起工作通常要好得多。一旦你开始使用它,我相信你会不想回去。
对于纯 SimpleDateFormat
解决方案,请参阅
当且仅当您只有两个可能的值(这里是 AM/PM),那么您可以用 SimpleDateFormat
这样做:
DateFormatSymbols dfs = DateFormatSymbols.getInstance(Locale.FRENCH);
dfs.setAmPmStrings(new String[] { "Matin", "Soir" });
SimpleDateFormat input = new SimpleDateFormat("hh:mm a", Locale.FRENCH);
input.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
input.setDateFormatSymbols(dfs);
Date parsed = input.parse("01:01 Matin");
// control of parsing
SimpleDateFormat output = new SimpleDateFormat("HH:mm");
output.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
System.out.println(output.format(parsed)); // 01:01 (24-hour-clock)
我在这里将时区设置为 GMT 以防止任何时区影响。如果需要,您可以偏离它(但需要小心)。
正如一些评论中提到的,我仍然不认为使用 AM/PM 字段真的适合英语以外的其他语言。例如,法语至少知道两个或更多值,例如 "nuit"(=night)或 "après-midi"(=afternoon)。但是对于旧的 API 或新的 java.time
-package(需要外部库,如 ICU4J 或 Time4J),这种方式是不可能的。
谢谢大家的回答。
正如我之前提到的,我无力更改代码库。
所以,我所做的是:
public void setBeginAMPM( String ampm ) {
if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.am" ))) {
_beginAMPM = "AM";
}
else if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.pm" ))) {
_beginAMPM = "PM";
}
else{
_beginAMPM = ampm;
}
}
public void setEndAMPM( String ampm ) {
if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.am" ))) {
_endAMPM = "AM";
}
else if(ampm.equals(new I18NStringFactory().getString("Calendar", _locale , "default.time.pm" ))) {
_endAMPM = "PM";
}
else{
_endAMPM = ampm;
}
}
_locale 值我从操作 class 传递到从 class。如果它不是英语,它将进入 if 块之一,或者如果是英语,它将默认进入 else 块。根据本地值,它从属性文件中获取 AM/PM 值并相应地进行转换。
我只是将 AM/PM 值从其他特定于语言环境的语言修改为英语,因为 SimpleDateFormat() 仅支持英语。
你们可以称之为丑陋的 hack,但你猜怎么着,它正在解决我的目的。