获取 ParseException:Kotlin 中不可解析的日期异常

问题描述

我正在尝试以以下格式将传入的 ISO 日期(如 (2021-02-15T00:00:00.000Z))显示到 Textview:“dd MM yyyy”。 但是在解析日期时出现以下错误

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
         Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
         Caused by: java.text.ParseException: Unparseable date: "2021-02-15T00:00:00.000Z"
            at java.text.DateFormat.parse(DateFormat.java:362)

这是 Kotlin 代码

val format = SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss'Z'",Locale.getDefault()
)
val initialConvertedDate = format.parse(customfield.value)

val simpleDateFormat = SimpleDateFormat(
    "dd MM yyyy",Locale.getDefault()
)
val finalDate = simpleDateFormat.format(initialConvertedDate)

tv2.text = finalDate

解决方法

使用模式 yyyy-MM-dd'T'HH:mm:ss.SSSXXX,其中 X 真正代表 timezone offset。在您的日期时间字符串中,时区偏移量是 Z,它代表祖鲁语并指定 UTC(时区偏移量 +00:00 小时)。

您使用的格式有两个问题:

  1. 它使 Z 作为字符文字,因此它不代表时区偏移。
  2. 它没有指定秒的小数部分,即 SSS

演示:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String args[]) throws ParseException {
        String strDateTime = "2021-02-15T00:00:00.000Z";
        SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX",Locale.getDefault());
        Date date = sdfInput.parse(strDateTime);
        SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MM yyyy");
        sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        String formatted = sdfOutput.format(date);
        System.out.println(formatted);
    }
}

输出:

15 02 2021

请注意,旧的日期时间 API(java.util 日期时间类型及其格式 API,SimpleDateFormat)已过时且容易出错。建议完全停止使用,改用java.timemodern date-time API*

使用现代日期时间 API 的演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String args[]) {
        String strDateTime = "2021-02-15T00:00:00.000Z";
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);

        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd MM yyyy");
        String formatted = dtfOutput.format(odt);
        System.out.println(formatted);
    }
}

输出:

2021-02-15T00:00Z
15 02 2021

请注意,现代日期时间 API 基于 ISO-8601,因此您无需显式使用 DateTimeFormatter 来解析 ISO- 中已存在的日期时间字符串8601 格式。

modern date-time API 中了解有关 Trail: Date Time* 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project