Local Date Time
The representation of a specific civil date and time without a reference to a particular time zone.
This class does not describe specific moments in time. For that, use Instant values instead. Instead, you can think of its instances as clock readings, which can be observed in a particular time zone. For example, 2020-08-30T18:43
is not a moment in time since someone in Berlin and Tokyo would witness this on their clocks at different times, but it is a LocalDateTime.
The main purpose of this class is to provide human-readable representations of Instant values, to transfer them as data, or to define future planned events that will have the same local datetime even if the time zone rules change. In all other cases, when a specific time zone is known, it is recommended to use Instant instead.
Arithmetic operations
The arithmetic on LocalDateTime values is not provided since it may give misleading results without accounting for time zone transitions.
For example, in Berlin, naively adding one day to 2021-03-27T02:16:20
without accounting for the time zone would result in 2021-03-28T02:16:20
. However, the resulting local datetime cannot be observed in that time zone because the clocks moved forward from 02:00
to 03:00
on that day. This is known as a "time gap" or a "spring forward" transition.
Similarly, the local datetime 2021-10-31T02:16:20
is ambiguous, because the clocks moved back from 03:00
to 02:00
. This is known as a "time overlap" or a "fall back" transition.
For these reasons, using LocalDateTime as an input to arithmetic operations is discouraged.
When only the date component is needed, without the time, use LocalDate instead. It provides well-defined date arithmetic.
If the time component must be taken into account, LocalDateTime should be converted to Instant using a specific time zone, and the arithmetic on Instant should be used.
val timeZone = TimeZone.of("Europe/Berlin")
val localDateTime = LocalDateTime(2021, 3, 27, 2, 16, 20)
val instant = localDateTime.toInstant(timeZone)
val instantOneDayLater = instant.plus(1, DateTimeUnit.DAY, timeZone)
val localDateTimeOneDayLater = instantOneDayLater.toLocalDateTime(timeZone)
// 2021-03-28T03:16:20, as 02:16:20 that day is in a time gap
val instantTwoDaysLater = instant.plus(2, DateTimeUnit.DAY, timeZone)
val localDateTimeTwoDaysLater = instantTwoDaysLater.toLocalDateTime(timeZone)
// 2021-03-29T02:16:20
Platform specifics
The range of supported years is platform-dependent, but at least is enough to represent dates of all instants between Instant.DISTANT_PAST and Instant.DISTANT_FUTURE.
On the JVM, there are LocalDateTime.toJavaLocalDateTime()
and java.time.LocalDateTime.toKotlinLocalDateTime()
extension functions to convert between kotlinx.datetime
and java.time
objects used for the same purpose. Similarly, on the Darwin platforms, there is a LocalDateTime.toNSDateComponents()
extension function.
Construction, serialization, and deserialization
Pitfall: since LocalDateTime is always constructed without specifying the time zone, it cannot validate whether the given date and time components are valid in the implied time zone. For example, 2021-03-28T02:16:20
is invalid in Berlin, as it falls into a time gap, but nothing prevents one from constructing such a LocalDateTime. Before using a LocalDateTime constructed using any API, please ensure that the result is valid in the implied time zone. The recommended pattern is to convert a LocalDateTime to Instant as soon as possible (see LocalDateTime.toInstant) and work with Instant values instead.
LocalDateTime can be constructed directly from its components, LocalDate and LocalTime, using the constructor. See sample 1.
Some additional constructors that directly accept the values from date and time fields are provided for convenience. See sample 2.
parse and toString methods can be used to obtain a LocalDateTime from and convert it to a string in the ISO 8601 extended format (for example, 2023-01-02T22:35:01
). See sample 3.
parse and LocalDateTime.format both support custom formats created with Format or defined in Formats. See sample 4.
Additionally, there are several kotlinx-serialization
serializers for LocalDateTime:
LocalDateTimeIso8601Serializer for the ISO 8601 extended format.
LocalDateTimeComponentSerializer for an object with components.
See also
for only the date part of the datetime value.
for only the time part of the datetime value.
for the representation of a specific moment in time independent of a time zone.
Samples
import kotlinx.datetime.*
import kotlinx.datetime.format.*
import kotlin.test.*
fun main() {
//sampleStart
// Converting a LocalDate and a LocalTime to a LocalDateTime value and getting them back
val date = LocalDate(2024, 2, 15)
val time = LocalTime(16, 48)
val dateTime = LocalDateTime(date, time)
check(dateTime.date == date)
check(dateTime.time == time)
check(dateTime == date.atTime(time))
check(dateTime == time.atDate(date))
//sampleEnd
}
import kotlinx.datetime.*
import kotlinx.datetime.format.*
import kotlin.test.*
fun main() {
//sampleStart
// Constructing a LocalDateTime value by specifying its components
val dateTime1 = LocalDateTime(year = 2021, monthNumber = 3, dayOfMonth = 27, hour = 2, minute = 16, second = 20)
val dateTime2 = LocalDateTime(
year = 2021, month = Month.MARCH, dayOfMonth = 27,
hour = 2, minute = 16, second = 20, nanosecond = 0
)
check(dateTime1 == dateTime2)
//sampleEnd
}
import kotlinx.datetime.*
import kotlinx.datetime.format.*
import kotlin.test.*
fun main() {
//sampleStart
// Parsing and formatting LocalDateTime values
val dateTime = LocalDateTime.parse("2024-02-15T08:30:15.1234567")
check(dateTime == LocalDate(2024, 2, 15).atTime(8, 30, 15, 123_456_700))
val formatted = dateTime.toString()
check(formatted == "2024-02-15T08:30:15.123456700")
//sampleEnd
}
import kotlinx.datetime.*
import kotlinx.datetime.format.*
import kotlin.test.*
fun main() {
//sampleStart
// Parsing and formatting LocalDateTime values using a custom format
val customFormat = LocalDateTime.Format {
date(LocalDate.Formats.ISO)
char(' ')
hour(); char(':'); minute(); char(':'); second()
char(','); secondFraction(fixedLength = 3)
}
val dateTime = LocalDate(2024, 2, 15)
.atTime(8, 30, 15, 123_456_789)
check(dateTime.format(customFormat) == "2024-02-15 08:30:15,123")
check(customFormat.parse("2024-02-15 08:30:15,123") ==
LocalDate(2024, 2, 15).atTime(8, 30, 15, 123_000_000)
)
check(dateTime.format(LocalDateTime.Formats.ISO) == "2024-02-15T08:30:15.123456789")
//sampleEnd
}
Constructors
Constructs a LocalDateTime instance from the given date and time components.
Constructs a LocalDateTime instance from the given date and time components.
Constructs a LocalDateTime instance by combining the given date and time parts.
Properties
Functions
Compares this
datetime value with the other datetime value. Returns zero if this value is equal to the other, a negative number if this value represents earlier civil time than the other, and a positive number if this value represents later civil time than the other.
Formats this value using the given format. Equivalent to calling DateTimeFormat.format on format with this
.
Returns an instant that corresponds to this civil datetime value in the specified timeZone.
Returns an instant that corresponds to this civil datetime value that happens at the specified UTC offset.
Converts this kotlinx.datetime.LocalDateTime value to a java.time.LocalDateTime value.
Converts the given LocalDate to NSDateComponents.