使用 Java 检测字符串格式的日期区域设置

Detect locale of a date which is in string format using Java

我有一个字符串格式的日期,比如 2017 年 12 月 11 日,我想检测该日期属于哪个语言环境。例如,在美国,日期写为 mm/dd/yyyy。所以对于上述日期,我的程序应该输出美国语言环境。根据输入,应该有不同的语言环境。

我无法在任何其他讨论中找到此问题的解决方案。我想检测日期的区域设置,即日期写入的区域格式。我以美国为例。日期可以是任何语言环境格式,例如英国、法国、德国等。

我建议您遍历可能的语言环境(Locale.getAvailableLocales() 或您自己希望能够检测的语言环境列表),每次使用 DateTimeFormatter.ofLocalizedDate() 和所有可能的样式( full、long、medium、short,或者只是那些你认为相关的)并尝试将你的字符串解析为一个日期。如果成功,您就有了一个可能的语言环境,但只是几种可能中的一种。以下方法 returns 给定日期字符串的所有可能语言环境的数组。

public static Locale[] possibleLocalesForDateString(String dateString) {
    Locale[] availableLocales = Locale.getAvailableLocales();
    return Arrays.stream(availableLocales)
            .filter(loc -> {
                for (FormatStyle style : FormatStyle.values()) {
                    DateTimeFormatter formatter 
                            = DateTimeFormatter.ofLocalizedDate(style).withLocale(loc);
                    try {
                        LocalDate.parse(dateString, formatter);
                        // succeeded; this is a possible locale
                        return true;
                    } catch (DateTimeParseException dtpe) {
                        // failed; ignore this locale/format style combination
                    }
                }
                return false;
            })
            .toArray(Locale[]::new);
}

在我的 Java 8 possibleLocalesForDateString("12/11/2017") returns 上有 50 个语言环境。从 160 个可用语言环境开始,该方法已减少到不到三分之一的可能性。该数组 包含美国语言环境,因为美国短格式使用两位数年份,而中等格式如 Dec 11, 2017.

其他结果:

  • 12/11/17 提供多达 67 种可能的语言环境,包括美国 (en_US) 和法国 (fr_FR)。该日期在美国被理解为 12 月 11 日,在法国被理解为 11 月 12 日。
  • 30/11/17 给出“仅”60 个语言环境。美国不再包括在内,法国仍然是。使用大于 12 的日期有助于缩小可能性。
  • 相反地,12/31/17 仅给出其余 7 个语言环境,包括美国;但还是有歧义
  • 正在尝试德语日期字符串:11.12.17。我得到了 30 个语言环境,包括德国 (de_DE)。

避免SimpleDateFormat。由于您使用 simpledateformat 标记了您的问题,我想提一下 SimpleDateFormat class 早已过时并且出了名的麻烦。 java.time,现代 Java 日期和时间 API 更易于使用。所以我在我的方法中使用 classes 和 API 中的枚举。

LinkOracle Tutorial on Date Time,其中解释了java.time的用法。您可以在那里找到许多其他资源。

没有。本地化的日期时间格式不明确。您的 12/11/2017 示例可以是 12 月 11 日或 11 月 12 日。请参阅 list of date format by country

分离 contentpresentation 的关注点。

  • 内容
    • java.time
      在您的 Java 应用中,日期时间值应由 java.time 对象表示(避免遗留日期时间 类)。
    • ISO 8601
      将日期时间值序列化为文本以进行存储或交换时,仅使用标准 ISO 8601 格式:2017-12-11 .幸运的是,java.time 类 在 parsing/generating 字符串时默认使用标准格式。
  • 演示文稿
    • Localize
      使用 Locale 生成本地化字符串,仅用于向用户展示,绝不能在内部用作数据。请参阅 DateTimeFormatter.ofLocalized… 方法。

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time类?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.