在android中将任何iso-8601格式转换为可读格式

wz3gfoph  于 2021-07-05  发布在  Java
关注(0)|答案(1)|浏览(598)

所以,我知道这是一个讨论得很好的问题,有很多问题和答案(主要是关于joda),还有新的类datetimeformatter和所有支持26级以上api的类。但我担心的是:
我的android应用程序支持21及以上版本
我从不同的API中得到了iso-8601日期/时间格式的多种变体:例如:a)“2020-09-03t17:03:11.719566z”b)“2021-03-05t18:30:00z”
所以,我需要在今天和那天之间找到#天。当我编写代码来解析其中一个时,另一个会命中我的catch块,反之亦然,所以我编写了一个嵌套的try/catch块来处理这两种情况…类似这样:

fun getFormattedDate(stringDate: String?): Long {
if (dueDateString.isNullOrEmpty())
    return 0
val today = Calendar.getInstance().time
try {
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH)
    val date = inputFormat.parse(dueDateString)
    return if (date != null) {
        val dueCalendar = Calendar.getInstance()
        dueCalendar.time = date
        getNoOfDays(today.time, dueCalendar.timeInMillis)
    } else
        0
} catch (ex: Exception) {
    ex.showLog()
    try {
val inputFormat1 = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH)
        val date = inputFormat1.parse(dueDateString)
        return if (date != null) {
            val dueCalendar = Calendar.getInstance()
            dueCalendar.time = date
            getNoOfDays(today.time, dueCalendar.timeInMillis)
        } else
            0
    } catch (exc: Exception) {
        exc.showLog()
        return 0
    }
}
}

我使用此函数查找两个日期之间的#天:

fun getDueDateAfterParsing(dueDateString: String?): Long {
val today = ZonedDateTime.ofInstant(now(), ZoneId.systemDefault())
val dueDate = ZonedDateTime.parse(
    dueDateString,
    DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault())
)
return ChronoUnit.DAYS.between(today, dueDate)
}

我很肯定,解决这个问题的办法不会这么复杂。iso-8601有这么多格式,所以我不能写适合所有情况的try/catch块,对吧?有人能帮我找到最简单的方法吗?
我也考虑过regex,他们中的大多数人最后都会说我猜是joda,但至少我想确定什么是最理想的方法或最好的方法。
提前谢谢你的帮助。

raogr8fs

raogr8fs1#

java.time和desugaring或threetenabp

你可以用 DateTimeFormatter 以及来自java.time的其他类,现代的java日期和时间api,在android api level 21及更高版本上有两种方式:
通过去糖化。
通过后端口;chrylis已经提到,甚至还有一款android版本的threetenabp。jsr-310(java.time最初在这里被描述)和android backport(android backport)的abp都是310。
对于这两种方式,请参见底部的链接。

代码

您甚至不需要指定格式化程序。

String stringWeGot = "2020-09-03T17:03:11.719566Z";
    Instant parsed = Instant.parse(stringWeGot);
    System.out.println(parsed);

输出:
2020-09-03t17:03:11.719566z
或者使用其他示例字符串:

String stringWeGot = "2021-03-05T18:30:00Z";

2021-03-05t18:30:00z
time的类将最常见的iso8601变体解析为它们的默认值,也就是说,没有显式的格式化程序。存在或不存在从0到9位小数的秒是内置的,甚至存在或不存在的秒本身。两者 Instant 以及 OffsetDateTime 可以按代码中所示的方式使用。
警告!如果出于某种原因选择了一个或多个格式化程序,请不要硬编码 Z 作为格式模式字符串中的文本。 Z 是utc的偏移量(为零),必须按此进行分析,否则在绝大多数android设备上会得到不正确的结果。
另外,在计算天数方面,java.time远远优于像java.time这样设计糟糕的旧类 Calendar . 编辑:在设备时区中计算截止日期前的天数的方法是正确的。仅供参考,我的做法是:

ZoneId zone = ZoneId.systemDefault();
    ZonedDateTime today = ZonedDateTime.now(zone);
    ZonedDateTime dueDate = parsed.atZone(zone);
    long daysUntilDue = ChronoUnit.DAYS.between(today, dueDate);
    System.out.println(daysUntilDue);

使用示例字符串 2021-03-05T18:30:00Z 刚才在欧洲/哥本哈根时区运行的结果是:
181

链接

oracle教程:date time解释如何使用java.time。
java规范请求(jsr)310,其中 java.time 第一次被描述。
三十后港工程 java.time 到Java6和Java7(jsr-310为310)。
通过desugaring提供Java8+API
threetenabp,android版threeten backport
问:如何在android项目中使用threetenabp,有非常透彻的解释。

相关问题