ThreeTenABP DateTime 解析器为 yyyy-MM-ddTHH:mm:ss formate 提供异常

ThreeTenABP DateTime parser giving exception for yyyy-MM-ddTHH:mm:ss formate

提问人:RKB 提问时间:9/23/2020 最后编辑:deHaarRKB 更新时间:9/24/2020 访问量:554

问:

我需要将 dateTime 转换为 millis,并且为此使用 ThreeTenABP,但无法解析 ex 的 dateTime。 并给出以下例外情况。StringOffSetDateTime.parseString"2020-08-14T20:05:00"

Caused by: org.threeten.bp.format.DateTimeParseException:  
Text '2020-09-22T20:35:00' could not be parsed:  
Unable to obtain OffsetDateTime from TemporalAccessor:  
DateTimeBuilder[, ISO, null, 2020-09-22, 20:35], type org.threeten.bp.format.DateTimeBuilder

我已经搜索过类似的问题,但找不到确切的解决方案。

以下是我在 Kotlin 中使用的代码。

val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss",
                                                                Locale.ROOT)
val givenDateString = event?.eventDateTime
val timeInMillis = OffsetDateTime.parse(givenDateString, formatter)
                                    .toInstant()
                                    .toEpochMilli()
Android 日期时间 kotlin threetenabp

评论

0赞 ADM 9/23/2020
stackoverflow.com/questions/35298214/......
0赞 Anonymous 9/24/2020
这回答了你的问题吗?无法从 TemporalAccessor 获取 OffsetDateTime

答:

3赞 deHaar 9/23/2020 #1

问题是您尝试解析为 .没有 a 就无法创建 an,但可以从中推导出 no(可以猜测它是 UTC,但猜测在这种情况下是不合适的)。StringOffsetDateTimeOffsetDateTimeZoneOffsetZoneOffsetString

您可以解析为 a(日期和一天中的时间的表示形式,没有区域或偏移量),然后添加/附加所需的偏移量。你甚至不需要自定义,因为你是 ISO 格式,可以使用默认的内置格式化程序进行解析:StringLocalDateTimeDateTimeFormatterString

fun main() {
    // example String
    val givenDateString = "2020-09-22T20:35:00"
    // determine the zone id of the device (you can alternatively set a fix one here)
    val localZoneId: ZoneId = ZoneId.systemDefault()
    // parse the String to a LocalDateTime
    val localDateTime = LocalDateTime.parse(givenDateString)
    // then create a ZonedDateTime by adding the zone id and convert it to an OffsetDateTime
    val odt: OffsetDateTime = localDateTime.atZone(zoneId).toOffsetDateTime()
    // get the time in epoch milliseconds
    val timeInMillis = odt.toInstant().toEpochMilli()
    // and print it
    println("$odt ==> $timeInMillis")
}

此示例代码生成以下输出(注意 datetime 表示中的尾随,这是小时的偏移量,UTC 时区,我在 Kotlin Playground 中编写了这段代码,它似乎有 UTC 时区 ;-)):Z+00:00

2020-09-22T20:35Z ==> 1600806900000

请注意,我用 ThreeTen ABP 尝试过这个,而不是用 ThreeTen ABP,它现在已经过时了,无法用于许多(较低的)Android 版本,因为有 Android API 脱糖。但是,这应该不会有什么不同,因为当我第一次尝试时,您的示例代码抛出了完全相同的异常,这意味着 ThreeTen 不应该为此负责。java.time

评论

0赞 RKB 9/23/2020
感谢您的详细回答!ZoneOffset 很有意义,因为它是 UTC。虽然我使用了 ThreeTenABP,因为它向后兼容,而 java.time 需要 min API 26。
0赞 deHaar 9/23/2020
@RKB不客气。看看我答案最后一段中的链接,如果您使用所需的 gradle 插件,(至少是其中的很大一部分)现在也可以在较低的 API 级别中使用。感谢您的接受和投票。java.time
1赞 Arvind Kumar Avinash 10/1/2020
不错的答案!只是一些附加信息:由于目标是计算纪元毫,因此可以写成 .之后,millis 可以计算为 或 。总之,转换为 instead 会使代码稍微简洁一些。val odt: OffsetDateTime = localDateTime.atZone(zoneId).toOffsetDateTime()val zdt: ZonedDateTime = localDateTime.atZone(ZoneOffset.UTC)zdt.toEpochSecond().1000zdt.toInstant().toEpochMilli()ZonedDateTimeOffsetDateTime