Синтаксический анализатор ThreeTenABP DateTime дает исключение для формата yyyy-MM-ddTHH:mm:ss

Мне нужно преобразовать дату и время String to millis, и я использую для этого ThreeTenABP, но OffSetDateTime.parse не может разобрать dateTime String что для ex. "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

Я уже просмотрел похожие вопросы, но не смог найти точного решения.

Ниже приведен код, который я использую в Котлине.

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()

1 ответ

Решение

Проблема заключается в отсутствии смещения в String что вы пытаетесь разобрать на OffsetDateTime. An OffsetDateTime невозможно создать без ZoneOffset но нет ZoneOffset можно вывести из этого String(можно было просто догадаться, что это UTC, но угадывать в такой ситуации не годится).

Вы можете разобрать String к LocalDateTime(представление даты и времени без зоны или смещения), а затем добавьте / прикрепите желаемое смещение. Вам даже не нужен кастом DateTimeFormatter потому что твой String имеет формат ISO и может быть проанализирован с помощью встроенного средства форматирования по умолчанию:

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")
}

этот пример кода дает следующий результат (обратите внимание на конечный Z в представлении datetime это смещение +00:00 часов, часовой пояс UTC, я написал этот код в Kotlin Playground, и кажется, что у него часовой пояс UTC;-)):

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

Обратите внимание, что я пробовал это с java.timeа не с ThreeTen ABP, который сейчас устарел для многих (более низких) версий Android, поскольку есть Android API Desugaring. Однако это не должно иметь значения, потому что ваш примерный код выдал точно такое же исключение, когда я попробовал его сначала, а это значит, что ThreeTen не виноват в этом.

Другие вопросы по тегам