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

Improve the KDoc #367

Merged
merged 35 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b6a6338
Improve the KDoc
dkhalanskyjb Mar 12, 2024
0a7298e
Fix typos and small mistakes
dkhalanskyjb Mar 18, 2024
e076439
Don't hyphenate ISO 8601 when used as a compound adjective
dkhalanskyjb Mar 21, 2024
ca9c739
Implement the first pack of fixes after the review
dkhalanskyjb Mar 21, 2024
c6dd47f
The second pack of changes
dkhalanskyjb Mar 22, 2024
1a4b0f9
Add samples for TimeZone, UtcOffset, and Month
dkhalanskyjb Apr 3, 2024
6883ffb
WIP: add samples for LocalTime
dkhalanskyjb Apr 4, 2024
671ee59
WIP: add samples for some formatting APIs
dkhalanskyjb Apr 5, 2024
bca9eab
More samples
dkhalanskyjb Apr 15, 2024
ba55ab6
Add samples for format builders
dkhalanskyjb Apr 15, 2024
85ab102
Samples for Date(Time)Period and Clock
dkhalanskyjb Apr 16, 2024
cccad01
fixup
dkhalanskyjb Apr 16, 2024
f3d4653
More samples; only LocalDate and Instant left
dkhalanskyjb Apr 16, 2024
77aff41
Samples for LocalDate
dkhalanskyjb Apr 16, 2024
d70657b
Finish adding samples
dkhalanskyjb Apr 17, 2024
3c956e0
Address the reviews
dkhalanskyjb Apr 17, 2024
788285c
Try to find the edge cases that work across platforms
dkhalanskyjb Apr 17, 2024
60ed765
reword
dkhalanskyjb Apr 17, 2024
fd8be7d
Update core/common/src/DateTimeUnit.kt
dkhalanskyjb Apr 19, 2024
1302b7e
Address the comments
dkhalanskyjb Apr 19, 2024
8f73a08
Clarify setting DateTimeComponents.month
dkhalanskyjb Apr 19, 2024
33a3717
Provide a one-line description for every sample
dkhalanskyjb Apr 19, 2024
a2af2de
More additions according to the reviews
dkhalanskyjb Apr 19, 2024
f7878af
feat: new docs review
danil-pavlov Apr 12, 2024
63644e6
Mention the relevant parts of ISO 8601 when describing formats
dkhalanskyjb Apr 30, 2024
e6b758e
Incorporate some more proofreading results
dkhalanskyjb Apr 30, 2024
517ae7a
Address the review
dkhalanskyjb May 1, 2024
f45e493
Address the review
dkhalanskyjb May 3, 2024
8a0e356
~fixup
dkhalanskyjb May 8, 2024
f70e422
Remove separate samples for Long overloads (plus a small fixup)
dkhalanskyjb May 10, 2024
6c1423a
Use yyyy instead of uuuu in the Unicode pattern sample
dkhalanskyjb May 10, 2024
fa59e05
Use Instant.fromEpochSeconds in samples more
dkhalanskyjb May 10, 2024
a529d44
Fix a broken sample reference
dkhalanskyjb May 10, 2024
a0a1335
Fix broken table rendering
dkhalanskyjb May 10, 2024
8851274
Properly display samples in Dokka
dkhalanskyjb May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ To convert back, use the companion object function `Instant.fromEpochMillisecond
### Converting instant and local date/time to and from the ISO 8601 string

`Instant`, `LocalDateTime`, `LocalDate` and `LocalTime` provide shortcuts for
parsing and formatting them using the extended ISO-8601 format.
parsing and formatting them using the extended ISO 8601 format.
The `toString()` function is used to convert the value to a string in that format, and
the `parse` function in companion object is used to parse a string representation back.

Expand All @@ -201,7 +201,7 @@ LocalTime.parse("12:0:03.999") // fails with an IllegalArgumentException

### Working with other string formats

When some data needs to be formatted in some format other than ISO-8601, one
When some data needs to be formatted in some format other than ISO 8601, one
can define their own format or use some of the predefined ones:

```kotlin
Expand Down
40 changes: 39 additions & 1 deletion core/common/src/Clock.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,71 @@ import kotlin.time.*
* A source of [Instant] values.
*
* See [Clock.System][Clock.System] for the clock instance that queries the operating system.
*
* It is not recommended to use [Clock.System] directly in the implementation. Instead, you can pass a
* [Clock] explicitly to the necessary functions or classes.
* This way, tests can be written deterministically by providing custom [Clock] implementations
* to the system under test.
qwwdfsad marked this conversation as resolved.
Show resolved Hide resolved
*/
public interface Clock {
qwwdfsad marked this conversation as resolved.
Show resolved Hide resolved
/**
* Returns the [Instant] corresponding to the current time, according to this clock.
*
* It is not guaranteed that calling [now] later will return a larger [Instant].
* In particular, for [Clock.System] it is completely expected that the opposite will happen,
* and it must be taken into account.
* See the [System] documentation for details.
*
* Even though [Instant] is defined to be on the UTC-SLS time scale, which enforces a specific way of handling
* leap seconds, [now] is not guaranteed to handle leap seconds in any specific way.
*/
public fun now(): Instant

/**
* The [Clock] instance that queries the operating system as its source of knowledge of time.
* The [Clock] instance that queries the platform-specific system clock as its source of time knowledge.
*
* Successive calls to [now] will not necessarily return increasing [Instant] values, and when they do,
* these increases will not necessarily correspond to the elapsed time.
*
* For example, when using [Clock.System], the following could happen:
* - [now] returns `2023-01-02T22:35:01Z`.
* - The system queries the Internet and recognizes that its clock needs adjusting.
* - [now] returns `2023-01-02T22:32:05Z`.
*
* When you need predictable intervals between successive measurements, consider using [TimeSource.Monotonic].
*
* For improved testability, you should avoid using [Clock.System] directly in the implementation
* and pass a [Clock] explicitly instead. For example:
*
* @sample kotlinx.datetime.test.samples.ClockSamples.system
* @sample kotlinx.datetime.test.samples.ClockSamples.dependencyInjection
*/
qwwdfsad marked this conversation as resolved.
Show resolved Hide resolved
public object System : Clock {
override fun now(): Instant = @Suppress("DEPRECATION_ERROR") Instant.now()
dkhalanskyjb marked this conversation as resolved.
Show resolved Hide resolved
}

/** A companion object used purely for namespacing. */
public companion object {

}
}

/**
* Returns the current date at the given [time zone][timeZone], according to [this Clock][this].
*
* The time zone is important because the current date is not the same in all time zones at the same instant.
*
* @sample kotlinx.datetime.test.samples.ClockSamples.todayIn
*/
public fun Clock.todayIn(timeZone: TimeZone): LocalDate =
now().toLocalDateTime(timeZone).date

qwwdfsad marked this conversation as resolved.
Show resolved Hide resolved
/**
* Returns a [TimeSource] that uses this [Clock] to mark a time instant and to find the amount of time elapsed since that mark.
*
* **Pitfall**: using this function with [Clock.System] is error-prone
* because [Clock.System] is not well suited for measuring time intervals.
* Please only use this conversion function on the [Clock] instances that are fully controlled programmatically.
qwwdfsad marked this conversation as resolved.
Show resolved Hide resolved
*/
@ExperimentalTime
public fun Clock.asTimeSource(): TimeSource.WithComparableMarks = object : TimeSource.WithComparableMarks {
Expand Down
189 changes: 169 additions & 20 deletions core/common/src/DateTimePeriod.kt

Large diffs are not rendered by default.

87 changes: 75 additions & 12 deletions core/common/src/DateTimeUnit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,79 @@ import kotlin.time.*
import kotlin.time.Duration.Companion.nanoseconds

/**
* A unit for measuring time.
* A unit for measuring time; for example, a second, 20 seconds, a day, a month, or a quarter.
*
* This class is used to express arithmetic operations like addition and subtraction on date-time values:
* for example, adding 10 days to a date-time value, subtracting 5 hours from a date-time value, or finding the
* number of 30-second intervals between two date-time values.
*
* ### Interaction with other entities
*
* Any [DateTimeUnit] can be used with [Instant.plus] or [Instant.minus] to
* find an instant that is some number of units away from the given instant.
* Also, [Instant.until] can be used to find the number of the given units between two instants.
*
* [DateTimeUnit.TimeBased] can be used in the [Instant] operations without specifying the time zone because
* [DateTimeUnit.TimeBased] is defined in terms of the passage of real-time and is independent of the time zone.
* Note that a calendar day is not considered identical to 24 hours, so using it does require specifying the time zone.
* See [DateTimeUnit.DayBased] for an explanation.
*
* [DateTimeUnit.DateBased] units can be used in the [LocalDate] operations: [LocalDate.plus], [LocalDate.minus], and
* [LocalDate.until].
*
* Arithmetic operations on [LocalDateTime] are not provided.
* Please see the [LocalDateTime] documentation for details.
*
* [DateTimePeriod] is a combination of [DateTimeUnit] values of every kind, used to express periods like
* "two days and three hours".
* [DatePeriod] is specifically a combination of [DateTimeUnit.DateBased] values.
* [DateTimePeriod] is more flexible than [DateTimeUnit] because it can express a combination of values with different
* kinds of units, but in exchange, the duration of time between two [Instant] or [LocalDate] values can be
* measured in terms of some [DateTimeUnit], but not [DateTimePeriod] or [DatePeriod].
*
* ### Construction, serialization, and deserialization
*
* See the predefined constants for time units, like [DateTimeUnit.NANOSECOND], [DateTimeUnit.DAY],
* [DateTimeUnit.MONTH], and others.
*
* Two ways are provided to create custom [DateTimeUnit] instances:
* - By multiplying an existing unit on the right by an integer scalar: for example, `DateTimeUnit.NANOSECOND * 10`.
* - By constructing an instance manually with [TimeBased], [DayBased], or [MonthBased]: for example,
* `TimeBased(nanoseconds = 10)`.
* - By multiplying an existing unit on the right by an integer scalar, for example, `DateTimeUnit.MICROSECOND * 10`.
* - By constructing an instance manually with [TimeBased], [DayBased], or [MonthBased], for example,
* `DateTimeUnit.TimeBased(nanoseconds = 10_000)`.
*
* Note that a calendar day is not considered identical to 24 hours. See [DateTimeUnit.DayBased] for a discussion.
* Also, [DateTimeUnit] can be serialized and deserialized using `kotlinx.serialization`:
* [DateTimeUnitSerializer], [DateBasedDateTimeUnitSerializer], [DayBasedDateTimeUnitSerializer],
* [MonthBasedDateTimeUnitSerializer], and [TimeBasedDateTimeUnitSerializer] are provided, with varying levels of
* specificity of the type they handle.
*
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.construction
*/
@Serializable(with = DateTimeUnitSerializer::class)
public sealed class DateTimeUnit {

/** Produces a date-time unit that is a multiple of this unit times the specified integer [scalar] value. */
/**
* Produces a date-time unit that is a multiple of this unit times the specified integer [scalar] value.
*
* @throws ArithmeticException if the result overflows.
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.multiplication
*/
public abstract operator fun times(scalar: Int): DateTimeUnit

/**
* A date-time unit that has the precise time duration.
* A [date-time unit][DateTimeUnit] that has the precise time duration.
*
* Such units are independent of the time zone.
* Any such unit can be represented as some fixed number of nanoseconds.
*
* @see DateTimeUnit for a description of date-time units in general.
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.timeBasedUnit
*/
@Serializable(with = TimeBasedDateTimeUnitSerializer::class)
public class TimeBased(
/**
* The length of this unit in nanoseconds.
*
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.timeBasedUnit
*/
public val nanoseconds: Long
) : DateTimeUnit() {
Expand Down Expand Up @@ -81,6 +126,8 @@ public sealed class DateTimeUnit {

/**
* The length of this unit as a [Duration].
*
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.timeBasedUnit
*/
public val duration: Duration
get() = nanoseconds.nanoseconds
Expand All @@ -94,11 +141,15 @@ public sealed class DateTimeUnit {
}

/**
* A date-time unit equal to some number of days or months.
* A [date-time unit][DateTimeUnit] equal to some number of days or months.
*
* Operations involving `DateBased` units are performed on dates. The same operations on [Instants][Instant]
* require a [TimeZone] to find the corresponding [LocalDateTimes][LocalDateTime] first to perform
* the operation with the date component of these `LocalDateTime` values.
*
* @see DateTimeUnit for a description of date-time units in general.
* @see DateTimeUnit.DayBased for specifically day-based units.
* @see DateTimeUnit.MonthBased for specifically month-based units.
*/
@Serializable(with = DateBasedDateTimeUnitSerializer::class)
public sealed class DateBased : DateTimeUnit() {
Expand All @@ -111,19 +162,25 @@ public sealed class DateTimeUnit {
}

/**
* A date-time unit equal to some number of calendar days.
* A [date-time unit][DateTimeUnit] equal to some number of calendar days.
*
* A calendar day is not considered identical to 24 hours, thus a `DayBased`-unit cannot be expressed as a multiple of some [TimeBased]-unit.
* A calendar day is not considered identical to 24 hours.
* Thus, a `DayBased` unit cannot be expressed as a multiple of some [TimeBased] unit.
*
* The reason lies in time zone transitions, because of which some days can be 23 or 25 hours.
* For example, we say that exactly a whole day has passed between `2019-10-27T02:59` and `2019-10-28T02:59`
* in Berlin, despite the fact that the clocks were turned back one hour, so there are, in fact, 25 hours
* between the two date-times.
*
* @see DateTimeUnit for a description of date-time units in general.
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.dayBasedUnit
*/
@Serializable(with = DayBasedDateTimeUnitSerializer::class)
public class DayBased(
/**
* The length of this unit in days.
*
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.dayBasedUnit
*/
public val days: Int
) : DateBased() {
Expand All @@ -145,14 +202,20 @@ public sealed class DateTimeUnit {
}

/**
* A date-time unit equal to some number of months.
* A [date-time unit][DateTimeUnit] equal to some number of months.
*
* Since different months have different number of days, a `MonthBased`-unit cannot be expressed a multiple of some [DayBased]-unit.
* Since different months have a different number of days, a `MonthBased` unit cannot be expressed
* as a multiple of some [DayBased]-unit.
*
* @see DateTimeUnit for a description of date-time units in general.
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.monthBasedUnit
*/
@Serializable(with = MonthBasedDateTimeUnitSerializer::class)
public class MonthBased(
dkhalanskyjb marked this conversation as resolved.
Show resolved Hide resolved
/**
* The length of this unit in months.
*
* @sample kotlinx.datetime.test.samples.DateTimeUnitSamples.monthBasedUnit
*/
public val months: Int
) : DateBased() {
Expand Down
14 changes: 12 additions & 2 deletions core/common/src/DayOfWeek.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ package kotlinx.datetime

/**
* The enumeration class representing the days of the week.
*
* Usually acquired from [LocalDate.dayOfWeek], but can be constructed using the `DayOfWeek` factory function that
* accepts the ISO 8601 day number. This number can be obtained from the [isoDayNumber] property.
*
* @sample kotlinx.datetime.test.samples.DayOfWeekSamples.usage
*/
public expect enum class DayOfWeek {
MONDAY,
Expand All @@ -19,12 +24,17 @@ public expect enum class DayOfWeek {
}

/**
* The ISO-8601 number of the given day of the week. Monday is 1, Sunday is 7.
* The ISO 8601 number of the given day of the week. Monday is 1, Sunday is 7.
*
* @sample kotlinx.datetime.test.samples.DayOfWeekSamples.isoDayNumber
*/
public val DayOfWeek.isoDayNumber: Int get() = ordinal + 1

/**
* Returns the [DayOfWeek] instance for the given ISO-8601 week day number. Monday is 1, Sunday is 7.
* Returns the [DayOfWeek] instance for the given ISO 8601 week day number. Monday is 1, Sunday is 7.
*
* @throws IllegalArgumentException if the day number is not in the range 1..7
* @sample kotlinx.datetime.test.samples.DayOfWeekSamples.constructorFunction
*/
public fun DayOfWeek(isoDayNumber: Int): DayOfWeek {
require(isoDayNumber in 1..7) { "Expected ISO day-of-week number in 1..7, got $isoDayNumber" }
Expand Down
4 changes: 2 additions & 2 deletions core/common/src/Exceptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package kotlinx.datetime

/**
* Thrown by date-time arithmetic operations if the result can not be computed or represented.
* Thrown by date-time arithmetic operations if the result cannot be computed or represented.
*/
public class DateTimeArithmeticException: RuntimeException {
public constructor(): super()
Expand All @@ -16,7 +16,7 @@ public class DateTimeArithmeticException: RuntimeException {
}

/**
* Thrown when attempting to construct a [TimeZone] with an invalid ID.
* Thrown when attempting to construct a [TimeZone] with an invalid ID or unavailable rules.
*/
public class IllegalTimeZoneException: IllegalArgumentException {
public constructor(): super()
Expand Down
Loading