根据语言使用不同的时间格式
Use different time formats according to language
我应该根据应用中的语言显示不同的时间格式。当设备是英文时,用户应该得到这样的时间格式:
18 March 2018, 2.30 pm
但是当用户的设备是德语时,他应该得到这样的时间格式:
18.03.2018, 14:30 Uhr
有什么方法可以通过将时间 String
格式化为 SimpleDateFormat
来做到这一点,或者我应该用另一种方式来做到这一点吗?如果可以,我该如何做到这一点?
我认为这行不通,但确实行得通。只需将您喜欢的格式放入字符串 xml 文件中即可:
<string name="date_time_format">dd MMMM yyyy, hh.mm a</string>
<string name="date_time_format">dd.MM.yyyy, HH:mm</string>
然后像这样在 SDF 中使用它:
SimpleDateFormat fmtOut = new SimpleDateFormat(context.getString(R.string.date_time_format), Locale.getDefault());
对于德语格式末尾的 "Uhr",我添加了一个占位符字符串,如下所示:
<string name="date_time_string">%s</string>
<string name="date_time_string">%s Uhr</string>
和 return 使用 String.format() 方法格式化的日期:
return String.format(context.getString(R.string.date_time_string), fmtOut.format(date));
试试这个代码片段。希望它能解决问题。
java.sql.Date date1 = new java.sql.Date((new Date()).getTime());
SimpleDateFormat formatNowDay = new SimpleDateFormat("dd");
SimpleDateFormat formatNowYear = new SimpleDateFormat("yyyy");
SimpleDateFormat sdf12 = new SimpleDateFormat("hh:mm aa");
SimpleDateFormat sdf24 = new SimpleDateFormat("HH:mm");
SimpleDateFormat germanSdf = new SimpleDateFormat("dd.MM.yyyy");
String currentDay = formatNowDay.format(date1);
String currentYear = formatNowYear.format(date1);
String time12 = sdf12.format(date1);
String time24 = sdf24.format(date1);
String germanTime = germanSdf.format(date1);
Calendar mCalendar = Calendar.getInstance();
String currentMonth = mCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
String engTime = currentDay+" "+currentMonth+" "+currentYear+", "+time12;
String germanFormat = germanTime+", "+time24+" Uhr";
一种替代方法是使用 java.text.DateFormat
:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.ENGLISH);
日期和时间样式(第一个和第二个参数)可以是SHORT
、MEDIUM
、LONG
或FULL
。如果需要,您可以使用 Locale.getDefault()
获取设备的默认语言。
我不确定哪种样式组合能满足您的需求 - 所有这些都给了我不同的输出,none 给了我您描述的那个。
那是因为 JVM 中嵌入了特定于语言环境的格式,我不确定它在不同的 API 级别和设备之间有何不同。
如果上面的解决方案有效,那就没问题了。否则,另一种方法是为每个区域设置特定的模式:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = // use some default pattern for other languages?
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
String formattedDate = sdf.format(new Date());
一个细节是,在我的 JVM 中,英语语言环境的 AM/PM 符号是大写的,因此您可能需要通过以下方式进行调整:
// change AM/PM to am/pm (only for English)
if ("en".equals(locale.getLanguage())) {
formattedDate = formattedDate.toLowerCase();
}
java.time API
在 API 级别 26 中,您可以使用具有相同 类 和功能的 java.time API. For lower levels, there's a nice backport。
这更好用。代码可能看起来相似,但 类 本身解决了 lots of internal issues of the old API.
您可以先尝试获取 JVM 的本地化模式,看看它们是否与您的输出匹配:
Locale locale = Locale.getDefault();
FormatStyle style = FormatStyle.MEDIUM;
String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(style, style, IsoChronology.INSTANCE, locale);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
或同上:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = ""; // use some default pattern?
}
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
String formattedDate = LocalDateTime.now().format(fmt);
在我的测试中,我遇到了同样的问题,即英语大写 AM/PM。您可以通过调用 toLowerCase()
解决此问题,但此 API 还允许您创建更灵活的格式化程序。
格式化程序是 thread-safe(而 SimpleDateFormat
不是),因此您可以根据语言创建格式化程序的静态映射,并根据需要多次重复使用它们:
// map of formatters
Map<String, DateTimeFormatter> formatterMap = new HashMap<>();
// English formatter
Map<Long, String> customAmPmSymbols = new HashMap<>();
customAmPmSymbols.put(0L, "am");
customAmPmSymbols.put(1L, "pm");
DateTimeFormatter f = new DateTimeFormatterBuilder()
// date/time
.appendPattern("dd MMMM yyyy, h.mm ")
// custom AM/PM symbols (lowercase)
.appendText(ChronoField.AMPM_OF_DAY, customAmPmSymbols)
// create formatter
.toFormatter(Locale.ENGLISH);
// add to map
formatterMap.put("en", f);
// German formatter
formatterMap.put("de", DateTimeFormatter.ofPattern("dd.MM.yyyy, HH:mm 'Uhr'", Locale.GERMAN));
// get device's locale
Locale locale = Locale.getDefault();
DateTimeFormatter fmt = formatterMap.get(locale.getLanguage());
if (fmt != null) {
String formattedDate = LocalDateTime.now().format(fmt);
}
我应该根据应用中的语言显示不同的时间格式。当设备是英文时,用户应该得到这样的时间格式:
18 March 2018, 2.30 pm
但是当用户的设备是德语时,他应该得到这样的时间格式:
18.03.2018, 14:30 Uhr
有什么方法可以通过将时间 String
格式化为 SimpleDateFormat
来做到这一点,或者我应该用另一种方式来做到这一点吗?如果可以,我该如何做到这一点?
我认为这行不通,但确实行得通。只需将您喜欢的格式放入字符串 xml 文件中即可:
<string name="date_time_format">dd MMMM yyyy, hh.mm a</string>
<string name="date_time_format">dd.MM.yyyy, HH:mm</string>
然后像这样在 SDF 中使用它:
SimpleDateFormat fmtOut = new SimpleDateFormat(context.getString(R.string.date_time_format), Locale.getDefault());
对于德语格式末尾的 "Uhr",我添加了一个占位符字符串,如下所示:
<string name="date_time_string">%s</string>
<string name="date_time_string">%s Uhr</string>
和 return 使用 String.format() 方法格式化的日期:
return String.format(context.getString(R.string.date_time_string), fmtOut.format(date));
试试这个代码片段。希望它能解决问题。
java.sql.Date date1 = new java.sql.Date((new Date()).getTime());
SimpleDateFormat formatNowDay = new SimpleDateFormat("dd");
SimpleDateFormat formatNowYear = new SimpleDateFormat("yyyy");
SimpleDateFormat sdf12 = new SimpleDateFormat("hh:mm aa");
SimpleDateFormat sdf24 = new SimpleDateFormat("HH:mm");
SimpleDateFormat germanSdf = new SimpleDateFormat("dd.MM.yyyy");
String currentDay = formatNowDay.format(date1);
String currentYear = formatNowYear.format(date1);
String time12 = sdf12.format(date1);
String time24 = sdf24.format(date1);
String germanTime = germanSdf.format(date1);
Calendar mCalendar = Calendar.getInstance();
String currentMonth = mCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
String engTime = currentDay+" "+currentMonth+" "+currentYear+", "+time12;
String germanFormat = germanTime+", "+time24+" Uhr";
一种替代方法是使用 java.text.DateFormat
:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.ENGLISH);
日期和时间样式(第一个和第二个参数)可以是SHORT
、MEDIUM
、LONG
或FULL
。如果需要,您可以使用 Locale.getDefault()
获取设备的默认语言。
我不确定哪种样式组合能满足您的需求 - 所有这些都给了我不同的输出,none 给了我您描述的那个。
那是因为 JVM 中嵌入了特定于语言环境的格式,我不确定它在不同的 API 级别和设备之间有何不同。
如果上面的解决方案有效,那就没问题了。否则,另一种方法是为每个区域设置特定的模式:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = // use some default pattern for other languages?
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
String formattedDate = sdf.format(new Date());
一个细节是,在我的 JVM 中,英语语言环境的 AM/PM 符号是大写的,因此您可能需要通过以下方式进行调整:
// change AM/PM to am/pm (only for English)
if ("en".equals(locale.getLanguage())) {
formattedDate = formattedDate.toLowerCase();
}
java.time API
在 API 级别 26 中,您可以使用具有相同 类 和功能的 java.time API. For lower levels, there's a nice backport。
这更好用。代码可能看起来相似,但 类 本身解决了 lots of internal issues of the old API.
您可以先尝试获取 JVM 的本地化模式,看看它们是否与您的输出匹配:
Locale locale = Locale.getDefault();
FormatStyle style = FormatStyle.MEDIUM;
String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(style, style, IsoChronology.INSTANCE, locale);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
或同上:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = ""; // use some default pattern?
}
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
String formattedDate = LocalDateTime.now().format(fmt);
在我的测试中,我遇到了同样的问题,即英语大写 AM/PM。您可以通过调用 toLowerCase()
解决此问题,但此 API 还允许您创建更灵活的格式化程序。
格式化程序是 thread-safe(而 SimpleDateFormat
不是),因此您可以根据语言创建格式化程序的静态映射,并根据需要多次重复使用它们:
// map of formatters
Map<String, DateTimeFormatter> formatterMap = new HashMap<>();
// English formatter
Map<Long, String> customAmPmSymbols = new HashMap<>();
customAmPmSymbols.put(0L, "am");
customAmPmSymbols.put(1L, "pm");
DateTimeFormatter f = new DateTimeFormatterBuilder()
// date/time
.appendPattern("dd MMMM yyyy, h.mm ")
// custom AM/PM symbols (lowercase)
.appendText(ChronoField.AMPM_OF_DAY, customAmPmSymbols)
// create formatter
.toFormatter(Locale.ENGLISH);
// add to map
formatterMap.put("en", f);
// German formatter
formatterMap.put("de", DateTimeFormatter.ofPattern("dd.MM.yyyy, HH:mm 'Uhr'", Locale.GERMAN));
// get device's locale
Locale locale = Locale.getDefault();
DateTimeFormatter fmt = formatterMap.get(locale.getLanguage());
if (fmt != null) {
String formattedDate = LocalDateTime.now().format(fmt);
}