根据语言使用不同的时间格式

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);

日期和时间样式(第一个和第二个参数)可以是SHORTMEDIUMLONGFULL。如果需要,您可以使用 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);
}