代码之家  ›  专栏  ›  技术社区  ›  Daria Pydorenko

如何在Java8中用阿拉伯印度教数字解析字符串datetime&timezone?

  •  0
  • Daria Pydorenko  · 技术社区  · 3 年前

    我想解析字符串datetime&带有阿拉伯印度教数字的时区,所以我写了这样一个代码:

        String dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+٠٢:٠٠";
        char zeroDigit = 'Ù ';
        Locale locale = Locale.forLanguageTag("ar");
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX")
                .withLocale(locale)
                .withDecimalStyle(DecimalStyle.of(locale).withZeroDigit(zeroDigit));
        ZonedDateTime parsedDateTime = ZonedDateTime.parse(dateTime, pattern);
        assert parsedDateTime != null;
    

    java.time.format.DateTimeParseException:无法在索引19处分析文本“--¨T::¨+:”

    我检查了很多关于Stackoverflow的问题,但我仍然不明白我做错了什么。

    它可以很好地与 dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+02:00" 时区不使用阿拉伯印度教数字时。

    0 回复  |  直到 3 年前
        1
  •  4
  •   Anonymous    3 年前

    你的 dateTime 字符串是错误的,被误解了。显然,它试图符合ISO8601格式,但失败了。因为ISO 8601格式使用US-ASCII数字。

    java.time的类( Instant , OffsetDateTime ZonedDateTime )如果ISO 8601中的数字是正确的,则将在没有任何格式化程序的情况下解析字符串。在绝大多数情况下,我会选择你的方法:尝试按原样解析字符串。在这种情况下没有。对我来说,在解析之前更正字符串更有意义。

        String dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+٠٢:٠٠";
        char[] dateTimeChars = dateTime.toCharArray();
        for (int index = 0; index < dateTimeChars.length; index++) {
            if (Character.isDigit(dateTimeChars[index])) {
                int digitValue = Character.getNumericValue(dateTimeChars[index]);
                dateTimeChars[index] = Character.forDigit(digitValue, 10);
            }
        }
        
        OffsetDateTime odt = OffsetDateTime.parse(CharBuffer.wrap(dateTimeChars));
        
        System.out.println(odt);
    

    输出:

    编辑:当然,如果你能教育字符串的发布者使用US-ASCII数字,那就更好了。

    编辑:我知道我链接到下面的维基百科文章说:

    以及特定的计算机字符(如“-”、““:”、“T”、“W”、“Z”) 标准中指定的特定含义;

    这是造成混乱的一个可以想象的原因。文章 链接到说:

    编辑:如何转换每个数字: Character.getNumericValue() 皈依 char 表示一个数字到另一个数字 int 'Ù ' 到0, 'Ù¢' 到2等。它适用于所有数字字符(不仅仅是阿拉伯语和ASCII字符)。 Character.forDigit() 执行某种相反的转换,仅始终转换为US ASCII,所以0到 '0' ,2至 '2'

    编辑:感谢@Holger让我注意到 CharBuffer 在这方面。A. CharBuffer 工具 CharSequence parse time的方法需要,因此可以避免转换 烧焦 数组返回到 String

    链接

        2
  •  4
  •   VGR    3 年前

    错误消息指出问题在输入字符串的索引19处。

    第19个字符是 + 输入字符串中的字符。这意味着偏移量(由 XXX

    问题不在于 + +05:00 ,则从未本地化。

    文档中没有提到这一点,所以我必须查看DateTimeFormatterBuilder的源代码来验证它。

    在那个班里是 this inner class :

    static final class OffsetIdPrinterParser implements DateTimePrinterParser {
    

    在那门课上,我们可以找到一个 parse method parseHour parseMinute parseSeconds 方法。

    这些方法中的每一个都委托给一个私有 parseDigits only ASCII digits are considered

    char ch1 = parseText.charAt(pos++);
    char ch2 = parseText.charAt(pos++);
    if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
        return false;
    }
    

    因此,这里的答案是,时区偏移量必须由ASCII数字组成,而与语言环境无关。