korlibs / korge

KorGE Game Engine. Multiplatform Kotlin Game Engine
https://korge.org/
Other
2.57k stars 124 forks source link

ISO8601 Intervals vs. Durations #677

Open dalewking opened 3 years ago

dalewking commented 3 years ago

Your ISO8601 class has several members that supposedly represent parsing and formatting of "intervals", but that is not really true. The support in that class is properly called a duration (see https://en.wikipedia.org/wiki/ISO_8601#Durations).

While a duration is one type of Interval (one that is only valid with additional context information) there are 3 other interval formats that you are not supporting (see .

I would like to see the current interval references deprecated and new ones created that properly call it Duration.

I would like to see support for time intervals (see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals) added that support the first 3 time interval formats, producing a DateTimeRange. You can call these TimeInterval to distinguish from the current incorrect terminology of Interval

soywiz commented 3 years ago

ISO was not used as reference for naming. The naming reference was the C# .NET API. One of the reasons was to avoid conflicting names when working on JVM source sets, that are usually a pain when dealing with imports. Never intended to be super strict with the naming.

If in your projects you prefer to see other names, you can use typealias to rename the classes to whatever fits your needs.

And if you believe there is a miss in some functionality regarding to representing time intervals, you can make a proposal PR adding them and discuss that there. This specific project is public domain, so contributions are welcome.

dalewking commented 3 years ago

Seems rather silly and confusing that ISO8601.INTERVAL does not actually represent an ISO8601 Interval.

Here is the function we wrote to parse an ISO8601 interval. It parses the first 3 forms of ISO8601 (since form 4 requires context it requires special handling and is really just an ISO8601 duration). This does not correspond to your parsing/formatting structure as all we needed was parsing, but perhaps it would help:

fun parseInterval(str: String): DateTimeRange =
    str.split("/")
        .takeIf { it.size == 2 }
        ?.let { (left, right) ->
            val rangeStart = ISO8601.DATE.tryParse(left, false)?.utc
            val rangeEnd = ISO8601.DATE.tryParse(right, false)?.utc

            when {
                rangeStart == null ->
                    rangeEnd?.let {
                        ISO8601.INTERVAL.tryParse(left, false)
                            ?.let { DateTimeRange(rangeEnd - it, rangeEnd) }
                    }

                rangeEnd == null ->
                    ISO8601.INTERVAL.tryParse(right, false)
                        ?.let { DateTimeRange(rangeStart, rangeStart + it) }

                else -> DateTimeRange(rangeStart, rangeEnd)
            }
        } ?: throw DateException("Interval $str is invalid")