Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DateTimeComponents.Format parse throws an exception when timeZoneId() is UTC #444

Open
LotuxPunk opened this issue Oct 16, 2024 · 1 comment
Labels
formatters Related to parsing and formatting

Comments

@LotuxPunk
Copy link

LotuxPunk commented Oct 16, 2024

I have this piece of code to handle a Long date (20241016153100) to an ISO8106 date, it works for most of the cases, but if tz is UTC, the id will be Z, and throw an exception.

DateTimeComponents.Format {
    year()
    monthNumber()
    dayOfMonth()
    hour()
    minute()
    second()
    char('|')
    timeZoneId()
}.parse("$date|${(tz.id)}").let {
    buildString {
        append(it.year.toString().padStart(2, '0'))
        append('-')
        append(it.monthNumber.toString().padStart(2, '0'))
        append('-')
        append(it.dayOfMonth.toString().padStart(2, '0'))
        append('T')
        append(it.hour.toString().padStart(2, '0'))
        append(':')
        append(it.minute.toString().padStart(2, '0'))
        append(':')
        append(it.second.toString().padStart(2, '0'))
        append(tz.offsetAt(it.toInstantUsingOffset()).asTimeZone().offset.toString())
    }
}
Errors: position 15: 'Expected timeZoneId but got ', position 0: 'Expected - but got 2', position 0: 'Expected + but got 2'kotlinx.datetime.DateTimeFormatException: Failed to parse value from '20231013000000|Z'

The workaround I have now is to change Z to Europe/London and it seems to works, but it would seems fair that timeZoneId could recognise Z as a valid timeZoneId.

@dkhalanskyjb dkhalanskyjb added the formatters Related to parsing and formatting label Oct 16, 2024
@LotuxPunk LotuxPunk changed the title DateTimeComponents.Format parse throws and exception when timeZoneId() is UTC DateTimeComponents.Format parse throws an exception when timeZoneId() is UTC Oct 16, 2024
@dkhalanskyjb
Copy link
Collaborator

Would this work instead?

import kotlinx.datetime.*
import kotlinx.datetime.format.*

fun main() {
    val tz = TimeZone.UTC
    val date = "20231013000000"
    val ldt = LocalDateTime.Format {
        year()
        monthNumber()
        dayOfMonth()
        hour()
        minute()
        second()
    }.parse(date)
    val instant = ldt.toInstant(tz)
    println(instant.format(DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET, tz.offsetAt(instant)))
}

Runnable version: https://pl.kotl.in/wJEhu6YbS

  • Why put the timezone into a string just to immediately parse it back?
  • .asTimeZone().offset shouldn't do anything.
  • append(x.toString()) is the same as append(x): see append(value: Any?) in https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-string-builder/append.html
  • Formatting in ISO 8601 by hand is not needed, we have such formatters already. For Instant, that's DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET.
  • There is no reason to parse DateTimeComponents when all you have is a LocalDateTime.
  • The year is padded to two digits, you probably meant 4. Also, wrong results for negative years.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
formatters Related to parsing and formatting
Projects
None yet
Development

No branches or pull requests

2 participants