DateTimeParseException - 无法在索引 15 处进行解析

adr*_*oir 2 datetime android date kotlin

我得到这个例外:

java.time.format.DateTimeParseException:无法在索引 15 处解析文本“02/16/21 09:11 PM”

我在这里做错了什么?

    private fun extractTimestamp(date: String, time: String): Long {
        val formatter = DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a")
        return LocalDateTime.parse("$date $time", formatter)
            .atZone(ZoneId.systemDefault())
            .toInstant().toEpochMilli()
    }
Run Code Online (Sandbox Code Playgroud)

索引 15 位于“PM”,09:11 是有效的 AM/PM 时间。

rzw*_*oot 5

Java有禁止的方法。你永远不应该给他们打电话。如果您的 IDE 能够在任何方法调用时生成警告(无论该方法出现在何处),请将这些方法添加到此列表中。

DateTimeFormatter.ofPattern(pattern) 是其中之一。这是被禁止的。不要使用它。

问题是,它假定您系统的区域设置。就您而言,它假定了英国区域设置。让我们反转练习:

LocalDateTime ldt = LocalDateTime.of(2021, 16, 2, 21, 11, 0);
System.out.println(ldt.format(DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a", Locale.UK)));

>02/16/21 09:11 pm

// huh.

LocalDateTime ldt = LocalDateTime.of(2021, 16, 2, 21, 11, 0);
System.out.println(ldt.format(DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a", Locale.ENGLISH)));

>02/16/21 09:11 PM

Run Code Online (Sandbox Code Playgroud)

嗯,看看那个。显然,在英国语言环境中,AM/PM 是小写的。

默认情况下,DTF区分大小写。这就是这里的全部错误;如果你尝试用小写pm来解析,它工作得很好。您可以明确要求不区分大小写,但这不是此处的解决方案。语言环境可能是中文或日文,并且可能a意味着完全不同的东西。

真正的解决方法是永远不要调用此方法,而是使用显式指定区域设置的覆盖。那个很好:

private fun extractTimestamp(date: String, time: String): Long {
        val formatter = DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a", Locale.ENGLISH)
        return LocalDateTime.parse("$date $time", formatter)
            .atZone(ZoneId.systemDefault())
            .toInstant().toEpochMilli()
    }
Run Code Online (Sandbox Code Playgroud)

我唯一改变的是我, Locale.ENGLISH在其中添加了内容。

有时,您需要实际使用平台默认值,例如向用户呈现时间时。我强烈建议您仍然跳过这些方法,而是使用Locale.getDefault(). 也许是多余的代码,但在这种情况下毫无疑问:通过明确应用默认值,使您的代码更容易阅读。例如,这很可能意味着您不必编写堆栈溢出答案。较短的代码并不总是更好的代码。