Skip to content

Add orNull functions for non-throwing construction of datetime entities #509

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

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions core/api/kotlinx-datetime.api
Original file line number Diff line number Diff line change
@@ -299,6 +299,8 @@ public final class kotlinx/datetime/LocalDate$Companion {
public final fun Format (Lkotlin/jvm/functions/Function1;)Lkotlinx/datetime/format/DateTimeFormat;
public final fun fromEpochDays (I)Lkotlinx/datetime/LocalDate;
public final fun fromEpochDays (J)Lkotlinx/datetime/LocalDate;
public final fun orNull (III)Lkotlinx/datetime/LocalDate;
public final fun orNull (ILkotlinx/datetime/Month;I)Lkotlinx/datetime/LocalDate;
public final fun parse (Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;)Lkotlinx/datetime/LocalDate;
public final synthetic fun parse (Ljava/lang/String;)Lkotlinx/datetime/LocalDate;
public static synthetic fun parse$default (Lkotlinx/datetime/LocalDate$Companion;Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;ILjava/lang/Object;)Lkotlinx/datetime/LocalDate;
@@ -375,6 +377,10 @@ public final class kotlinx/datetime/LocalDateTime : java/io/Serializable, java/l

public final class kotlinx/datetime/LocalDateTime$Companion {
public final fun Format (Lkotlin/jvm/functions/Function1;)Lkotlinx/datetime/format/DateTimeFormat;
public final fun orNull (IIIIIII)Lkotlinx/datetime/LocalDateTime;
public final fun orNull (ILkotlinx/datetime/Month;IIIII)Lkotlinx/datetime/LocalDateTime;
public static synthetic fun orNull$default (Lkotlinx/datetime/LocalDateTime$Companion;IIIIIIIILjava/lang/Object;)Lkotlinx/datetime/LocalDateTime;
public static synthetic fun orNull$default (Lkotlinx/datetime/LocalDateTime$Companion;ILkotlinx/datetime/Month;IIIIIILjava/lang/Object;)Lkotlinx/datetime/LocalDateTime;
public final fun parse (Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;)Lkotlinx/datetime/LocalDateTime;
public final synthetic fun parse (Ljava/lang/String;)Lkotlinx/datetime/LocalDateTime;
public static synthetic fun parse$default (Lkotlinx/datetime/LocalDateTime$Companion;Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;ILjava/lang/Object;)Lkotlinx/datetime/LocalDateTime;
@@ -420,6 +426,8 @@ public final class kotlinx/datetime/LocalTime$Companion {
public final fun fromMillisecondOfDay (I)Lkotlinx/datetime/LocalTime;
public final fun fromNanosecondOfDay (J)Lkotlinx/datetime/LocalTime;
public final fun fromSecondOfDay (I)Lkotlinx/datetime/LocalTime;
public final fun orNull (IIII)Lkotlinx/datetime/LocalTime;
public static synthetic fun orNull$default (Lkotlinx/datetime/LocalTime$Companion;IIIIILjava/lang/Object;)Lkotlinx/datetime/LocalTime;
public final fun parse (Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;)Lkotlinx/datetime/LocalTime;
public final synthetic fun parse (Ljava/lang/String;)Lkotlinx/datetime/LocalTime;
public static synthetic fun parse$default (Lkotlinx/datetime/LocalTime$Companion;Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;ILjava/lang/Object;)Lkotlinx/datetime/LocalTime;
@@ -526,6 +534,8 @@ public final class kotlinx/datetime/UtcOffset : java/io/Serializable {
public final class kotlinx/datetime/UtcOffset$Companion {
public final fun Format (Lkotlin/jvm/functions/Function1;)Lkotlinx/datetime/format/DateTimeFormat;
public final fun getZERO ()Lkotlinx/datetime/UtcOffset;
public final fun orNull (Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)Lkotlinx/datetime/UtcOffset;
public static synthetic fun orNull$default (Lkotlinx/datetime/UtcOffset$Companion;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lkotlinx/datetime/UtcOffset;
public final fun parse (Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;)Lkotlinx/datetime/UtcOffset;
public final synthetic fun parse (Ljava/lang/String;)Lkotlinx/datetime/UtcOffset;
public static synthetic fun parse$default (Lkotlinx/datetime/UtcOffset$Companion;Ljava/lang/CharSequence;Lkotlinx/datetime/format/DateTimeFormat;ILjava/lang/Object;)Lkotlinx/datetime/UtcOffset;
6 changes: 6 additions & 0 deletions core/api/kotlinx-datetime.klib.api
Original file line number Diff line number Diff line change
@@ -362,6 +362,8 @@ final class kotlinx.datetime/LocalDate : kotlin/Comparable<kotlinx.datetime/Loca
final fun Format(kotlin/Function1<kotlinx.datetime.format/DateTimeFormatBuilder.WithDate, kotlin/Unit>): kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/LocalDate> // kotlinx.datetime/LocalDate.Companion.Format|Format(kotlin.Function1<kotlinx.datetime.format.DateTimeFormatBuilder.WithDate,kotlin.Unit>){}[0]
final fun fromEpochDays(kotlin/Int): kotlinx.datetime/LocalDate // kotlinx.datetime/LocalDate.Companion.fromEpochDays|fromEpochDays(kotlin.Int){}[0]
final fun fromEpochDays(kotlin/Long): kotlinx.datetime/LocalDate // kotlinx.datetime/LocalDate.Companion.fromEpochDays|fromEpochDays(kotlin.Long){}[0]
final fun orNull(kotlin/Int, kotlin/Int, kotlin/Int): kotlinx.datetime/LocalDate? // kotlinx.datetime/LocalDate.Companion.orNull|orNull(kotlin.Int;kotlin.Int;kotlin.Int){}[0]
final fun orNull(kotlin/Int, kotlinx.datetime/Month, kotlin/Int): kotlinx.datetime/LocalDate? // kotlinx.datetime/LocalDate.Companion.orNull|orNull(kotlin.Int;kotlinx.datetime.Month;kotlin.Int){}[0]
final fun parse(kotlin/CharSequence, kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/LocalDate> = ...): kotlinx.datetime/LocalDate // kotlinx.datetime/LocalDate.Companion.parse|parse(kotlin.CharSequence;kotlinx.datetime.format.DateTimeFormat<kotlinx.datetime.LocalDate>){}[0]
final fun parse(kotlin/String): kotlinx.datetime/LocalDate // kotlinx.datetime/LocalDate.Companion.parse|parse(kotlin.String){}[0]
final fun serializer(): kotlinx.serialization/KSerializer<kotlinx.datetime/LocalDate> // kotlinx.datetime/LocalDate.Companion.serializer|serializer(){}[0]
@@ -414,6 +416,8 @@ final class kotlinx.datetime/LocalDateTime : kotlin/Comparable<kotlinx.datetime/

final object Companion { // kotlinx.datetime/LocalDateTime.Companion|null[0]
final fun Format(kotlin/Function1<kotlinx.datetime.format/DateTimeFormatBuilder.WithDateTime, kotlin/Unit>): kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/LocalDateTime> // kotlinx.datetime/LocalDateTime.Companion.Format|Format(kotlin.Function1<kotlinx.datetime.format.DateTimeFormatBuilder.WithDateTime,kotlin.Unit>){}[0]
final fun orNull(kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int = ..., kotlin/Int = ...): kotlinx.datetime/LocalDateTime? // kotlinx.datetime/LocalDateTime.Companion.orNull|orNull(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int){}[0]
final fun orNull(kotlin/Int, kotlinx.datetime/Month, kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int = ..., kotlin/Int = ...): kotlinx.datetime/LocalDateTime? // kotlinx.datetime/LocalDateTime.Companion.orNull|orNull(kotlin.Int;kotlinx.datetime.Month;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int){}[0]
final fun parse(kotlin/CharSequence, kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/LocalDateTime> = ...): kotlinx.datetime/LocalDateTime // kotlinx.datetime/LocalDateTime.Companion.parse|parse(kotlin.CharSequence;kotlinx.datetime.format.DateTimeFormat<kotlinx.datetime.LocalDateTime>){}[0]
final fun parse(kotlin/String): kotlinx.datetime/LocalDateTime // kotlinx.datetime/LocalDateTime.Companion.parse|parse(kotlin.String){}[0]
final fun serializer(): kotlinx.serialization/KSerializer<kotlinx.datetime/LocalDateTime> // kotlinx.datetime/LocalDateTime.Companion.serializer|serializer(){}[0]
@@ -450,6 +454,7 @@ final class kotlinx.datetime/LocalTime : kotlin/Comparable<kotlinx.datetime/Loca
final fun fromMillisecondOfDay(kotlin/Int): kotlinx.datetime/LocalTime // kotlinx.datetime/LocalTime.Companion.fromMillisecondOfDay|fromMillisecondOfDay(kotlin.Int){}[0]
final fun fromNanosecondOfDay(kotlin/Long): kotlinx.datetime/LocalTime // kotlinx.datetime/LocalTime.Companion.fromNanosecondOfDay|fromNanosecondOfDay(kotlin.Long){}[0]
final fun fromSecondOfDay(kotlin/Int): kotlinx.datetime/LocalTime // kotlinx.datetime/LocalTime.Companion.fromSecondOfDay|fromSecondOfDay(kotlin.Int){}[0]
final fun orNull(kotlin/Int, kotlin/Int, kotlin/Int = ..., kotlin/Int = ...): kotlinx.datetime/LocalTime? // kotlinx.datetime/LocalTime.Companion.orNull|orNull(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int){}[0]
final fun parse(kotlin/CharSequence, kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/LocalTime> = ...): kotlinx.datetime/LocalTime // kotlinx.datetime/LocalTime.Companion.parse|parse(kotlin.CharSequence;kotlinx.datetime.format.DateTimeFormat<kotlinx.datetime.LocalTime>){}[0]
final fun parse(kotlin/String): kotlinx.datetime/LocalTime // kotlinx.datetime/LocalTime.Companion.parse|parse(kotlin.String){}[0]
final fun serializer(): kotlinx.serialization/KSerializer<kotlinx.datetime/LocalTime> // kotlinx.datetime/LocalTime.Companion.serializer|serializer(){}[0]
@@ -474,6 +479,7 @@ final class kotlinx.datetime/UtcOffset { // kotlinx.datetime/UtcOffset|null[0]
final fun <get-ZERO>(): kotlinx.datetime/UtcOffset // kotlinx.datetime/UtcOffset.Companion.ZERO.<get-ZERO>|<get-ZERO>(){}[0]

final fun Format(kotlin/Function1<kotlinx.datetime.format/DateTimeFormatBuilder.WithUtcOffset, kotlin/Unit>): kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/UtcOffset> // kotlinx.datetime/UtcOffset.Companion.Format|Format(kotlin.Function1<kotlinx.datetime.format.DateTimeFormatBuilder.WithUtcOffset,kotlin.Unit>){}[0]
final fun orNull(kotlin/Int? = ..., kotlin/Int? = ..., kotlin/Int? = ...): kotlinx.datetime/UtcOffset? // kotlinx.datetime/UtcOffset.Companion.orNull|orNull(kotlin.Int?;kotlin.Int?;kotlin.Int?){}[0]
final fun parse(kotlin/CharSequence, kotlinx.datetime.format/DateTimeFormat<kotlinx.datetime/UtcOffset> = ...): kotlinx.datetime/UtcOffset // kotlinx.datetime/UtcOffset.Companion.parse|parse(kotlin.CharSequence;kotlinx.datetime.format.DateTimeFormat<kotlinx.datetime.UtcOffset>){}[0]
final fun parse(kotlin/String): kotlinx.datetime/UtcOffset // kotlinx.datetime/UtcOffset.Companion.parse|parse(kotlin.String){}[0]
final fun serializer(): kotlinx.serialization/KSerializer<kotlinx.datetime/UtcOffset> // kotlinx.datetime/UtcOffset.Companion.serializer|serializer(){}[0]
39 changes: 39 additions & 0 deletions core/common/src/LocalDate.kt
Original file line number Diff line number Diff line change
@@ -68,6 +68,41 @@ import kotlin.internal.*
@Serializable(with = LocalDateIso8601Serializer::class)
public expect class LocalDate : Comparable<LocalDate> {
public companion object {
/**
* Constructs a [LocalDate] instance from the given date components
* or returns `null` if a value is out of range or invalid.
*
* The components [month] and [day] are 1-based.
*
* The supported ranges of components:
* - [year] the range is at least enough to represent dates of all instants between
* [Instant.DISTANT_PAST] and [Instant.DISTANT_FUTURE]
* - [month] `1..12`
* - [day] `1..31`, the upper bound can be less, depending on the month
*
* Use `LocalDate(year, month, day) to throw an exception
* instead of returning `null` when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateSamples.orNullMonthNumber
*/
public fun orNull(year: Int, month: Int, day: Int): LocalDate?

/**
* Constructs a [LocalDate] instance from the given date components
* or returns `null` if a value is out of range or invalid.
*
* The supported ranges of components:
* - [year] the range at least is enough to represent dates of all instants between
* [Instant.DISTANT_PAST] and [Instant.DISTANT_FUTURE]
* - [month] all values of the [Month] enum
* - [day] `1..31`, the upper bound can be less, depending on the month
*
* Use `LocalDate(year, month, day) to throw an exception
* instead of returning `null` when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateSamples.orNull
*/
public fun orNull(year: Int, month: Month, day: Int): LocalDate?
/**
* A shortcut for calling [DateTimeFormat.parse].
*
@@ -176,6 +211,8 @@ public expect class LocalDate : Comparable<LocalDate> {
*
* @throws IllegalArgumentException if any parameter is out of range or if [day] is invalid for the
* given [month] and [year].
* @see orNull for a version that returns `null` instead of throwing an exception
* when the parameters are invalid.
* @sample kotlinx.datetime.test.samples.LocalDateSamples.constructorFunctionMonthNumber
*/
public constructor(year: Int, month: Int, day: Int)
@@ -191,6 +228,8 @@ public expect class LocalDate : Comparable<LocalDate> {
*
* @throws IllegalArgumentException if any parameter is out of range or if [day] is invalid for the
* given [month] and [year].
* @see orNull for a version that returns `null` instead of throwing an exception
* when the parameters are invalid.
* @sample kotlinx.datetime.test.samples.LocalDateSamples.constructorFunction
*/
public constructor(year: Int, month: Month, day: Int)
64 changes: 64 additions & 0 deletions core/common/src/LocalDateTime.kt
Original file line number Diff line number Diff line change
@@ -114,6 +114,67 @@ import kotlin.jvm.JvmName
public expect class LocalDateTime : Comparable<LocalDateTime> {
public companion object {

/**
* Constructs a [LocalDateTime] instance from the given date and time components
* or returns `null` if a value is out of range.
*
* The components [month] and [day] are 1-based.
*
* The supported ranges of components:
* - [year] the range is platform-dependent, but at least is enough to represent dates of all instants between
* [Instant.DISTANT_PAST] and [Instant.DISTANT_FUTURE]
* - [month] `1..12`
* - [day] `1..31`, the upper bound can be less, depending on the month
* - [hour] `0..23`
* - [minute] `0..59`
* - [second] `0..59`
* - [nanosecond] `0..999_999_999`
*
* Use `LocalDateTime(year, month, day, hour, minute, second, nanosecond)`
* to throw an exception instead of returning `null` when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.orNull
*/
public fun orNull(
year: Int,
month: Int,
day: Int,
hour: Int,
minute: Int,
second: Int = 0,
nanosecond: Int = 0
): LocalDateTime?

/**
* Constructs a [LocalDateTime] instance from the given date and time components
* or returns `null` if a value is out of range.
*
* The supported ranges of components:
* - [year] the range is platform-dependent, but at least is enough to represent dates of all instants between
* [Instant.DISTANT_PAST] and [Instant.DISTANT_FUTURE]
* - [month] all values of the [Month] enum
* - [day] `1..31`, the upper bound can be less, depending on the month
* - [hour] `0..23`
* - [minute] `0..59`
* - [second] `0..59`
* - [nanosecond] `0..999_999_999`
*
* Use `LocalDateTime(year, month, day, hour, minute, second, nanosecond)`
* to throw an exception instead of returning `null` when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.orNullWithMonth
*/
public fun orNull(
year: Int,
month: Month,
day: Int,
hour: Int,
minute: Int,
second: Int = 0,
nanosecond: Int = 0
): LocalDateTime?


/**
* A shortcut for calling [DateTimeFormat.parse].
*
@@ -213,6 +274,7 @@ public expect class LocalDateTime : Comparable<LocalDateTime> {
*
* @throws IllegalArgumentException if any parameter is out of range
* or if [day] is invalid for the given [monthNumber] and [year].
* @see orNull for a version that returns `null` instead of throwing an exception when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.constructorFunctionWithMonthNumber
*/
@@ -241,6 +303,7 @@ public expect class LocalDateTime : Comparable<LocalDateTime> {
*
* @throws IllegalArgumentException if any parameter is out of range,
* or if [day] is invalid for the given [month] and [year].
* @see orNull for a version that returns `null` instead of throwing an exception when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.constructorFunction
*/
@@ -257,6 +320,7 @@ public expect class LocalDateTime : Comparable<LocalDateTime> {
/**
* Constructs a [LocalDateTime] instance by combining the given [date] and [time] parts.
*
* @see orNull for a version that returns `null` instead of throwing an exception when the parameters are invalid.
* @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.fromDateAndTime
*/
public constructor(date: LocalDate, time: LocalTime)
18 changes: 18 additions & 0 deletions core/common/src/LocalTime.kt
Original file line number Diff line number Diff line change
@@ -84,6 +84,23 @@ import kotlin.jvm.JvmName
public expect class LocalTime : Comparable<LocalTime> {
public companion object {

/**
* Constructs a [LocalTime] instance from the given time components
* or returns `null` if a value is out of range.
*
* The supported ranges of components:
* - [hour] `0..23`
* - [minute] `0..59`
* - [second] `0..59`
* - [nanosecond] `0..999_999_999`
*
* Use `LocalTime(hour, minute, second, nanosecond)`
* to throw an exception instead of returning `null` when the parameters are invalid.
*
* @sample kotlinx.datetime.test.samples.LocalTimeSamples.orNull
*/
public fun orNull(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0): LocalTime?

/**
* A shortcut for calling [DateTimeFormat.parse].
*
@@ -230,6 +247,7 @@ public expect class LocalTime : Comparable<LocalTime> {
* - [nanosecond] `0..999_999_999`
*
* @throws IllegalArgumentException if any parameter is out of range.
* @see orNull for a version that returns `null` instead of throwing an exception when the parameters are invalid.
* @sample kotlinx.datetime.test.samples.LocalTimeSamples.constructorFunction
*/
public constructor(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0)
4 changes: 3 additions & 1 deletion core/common/src/Month.kt
Original file line number Diff line number Diff line change
@@ -72,6 +72,8 @@ public val Month.number: Int get() = ordinal + 1
* @sample kotlinx.datetime.test.samples.MonthSamples.constructorFunction
*/
public fun Month(number: Int): Month {
require(number in 1..12)
require(number in 1..12) {
"Month must be a number between 1 and 12, got $number"
}
return Month.entries[number - 1]
}
Loading