-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathTimeZone.kt
280 lines (256 loc) · 12.2 KB
/
TimeZone.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
* Copyright 2019-2020 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/
@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("TimeZoneKt")
package kotlinx.datetime
import kotlinx.datetime.serializers.*
import kotlinx.serialization.Serializable
/**
* A time zone, provides the conversion between [Instant] and [LocalDateTime] values
* using a collection of rules specifying which [LocalDateTime] value corresponds to each [Instant].
*
* A time zone can be used in [Instant.toLocalDateTime] and [LocalDateTime.toInstant], and also in
* those arithmetic operations on [Instant] that require knowing the calendar.
*
* A [TimeZone] can be constructed using the [TimeZone.of] function, which accepts the string identifier, like
* `"Europe/Berlin"`, `"America/Los_Angeles"`, etc. For a list of such identifiers, see [TimeZone.availableZoneIds].
* Also, the constant [TimeZone.UTC] is provided for the UTC time zone.
*
* For interaction with `kotlinx-serialization`, [TimeZoneSerializer] is provided that serializes the time zone as its
* identifier.
*
* On the JVM, there are `TimeZone.toJavaZoneId()` and `java.time.ZoneId.toKotlinTimeZone()`
* extension functions to convert between `kotlinx.datetime` and `java.time` objects used for the same purpose.
* Similarly, on the Darwin platforms, there are `TimeZone.toNSTimeZone()` and `NSTimeZone.toKotlinTimeZone()` extension
* functions.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.usage
*/
@Serializable(with = TimeZoneSerializer::class)
public expect open class TimeZone {
/**
* Returns the identifier string of the time zone.
*
* This identifier can be used later for finding this time zone with [TimeZone.of] function.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.id
*/
public val id: String
/**
* Equivalent to [id].
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.equalsSample
*/
public override fun toString(): String
/**
* Compares this time zone to the other one. Time zones are equal if their identifier is the same.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.equalsSample
*/
public override fun equals(other: Any?): Boolean
public companion object {
/**
* Queries the current system time zone.
*
* If the current system time zone changes, this function can reflect this change on the next invocation.
*
* On Linux, this function queries the `/etc/localtime` symbolic link. If the link is missing, [UTC] is used.
* If the link points to an invalid location, [IllegalTimeZoneException] is thrown.
*
* Always returns the `UTC` timezone on the Wasm WASI platform due to the lack of support for retrieving system timezone information.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.currentSystemDefault
*/
public fun currentSystemDefault(): TimeZone
/**
* Returns the time zone with the fixed UTC+0 offset.
*
* The [id] of this time zone is `"Z"`.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.utc
*/
public val UTC: FixedOffsetTimeZone
/**
* Returns the time zone identified by the provided [zoneId].
*
* The supported variants of time zone identifiers:
* - `Z`, 'UTC', 'UT' or 'GMT' — identifies the fixed-offset time zone [TimeZone.UTC],
* - a string starting with '+', '-', `UTC+`, `UTC-`, `UT+`, `UT-`, `GMT+`, `GMT-` — identifiers the time zone
* with the fixed offset specified after `+` or `-`,
* - all other strings are treated as region-based zone identifiers.
* In the IANA Time Zone Database (TZDB) which is used as the default source of time zones,
* these ids are usually in the form `area/city`, for example, `Europe/Berlin` or `America/Los_Angeles`.
*
* It is guaranteed that passing any value from [availableZoneIds] to this function will return
* a valid time zone.
*
* @throws IllegalTimeZoneException if [zoneId] has an invalid format or a time-zone with the name [zoneId]
* is not found.
*
* @throws IllegalTimeZoneException on the Wasm WASI platform for non-fixed-offset time zones,
* unless a dependency on the `kotlinx-datetime-zoneinfo` artifact is added.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.constructorFunction
*/
public fun of(zoneId: String): TimeZone
/**
* Queries the set of identifiers of time zones available in the system.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.availableZoneIds
*/
public val availableZoneIds: Set<String>
}
/**
* Return the civil datetime value that this instant has in the time zone provided as an implicit receiver.
*
* Note that while this conversion is unambiguous, the inverse ([LocalDateTime.toInstant])
* is not necessarily so.
*
* @see LocalDateTime.toInstant
* @see Instant.offsetIn
* @throws DateTimeArithmeticException if this value is too large to fit in [LocalDateTime].
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.toLocalDateTimeWithTwoReceivers
*/
public fun Instant.toLocalDateTime(): LocalDateTime
/**
* Returns an instant that corresponds to this civil datetime value in the time zone provided as an implicit receiver.
*
* Note that the conversion is not always well-defined. There can be the following possible situations:
* - Only one instant has this datetime value in the [timeZone].
* In this case, the conversion is unambiguous.
* - No instant has this datetime value in the [timeZone].
* Such a situation appears when the time zone experiences a transition from a lesser to a greater offset.
* In this case, the conversion is performed with the lesser (earlier) offset, as if the time gap didn't occur yet.
* - Two possible instants can have these datetime components in the [timeZone].
* In this case, the earlier instant is returned.
*
* @see Instant.toLocalDateTime
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.toInstantWithTwoReceivers
*/
public fun LocalDateTime.toInstant(): Instant
}
/**
* A time zone that is known to always have the same offset from UTC.
*
* [TimeZone.of] will return an instance of this class if the time zone rules are fixed.
*
* Time zones that are [FixedOffsetTimeZone] at some point in time can become non-fixed in the future due to
* changes in legislation or other reasons.
*
* On the JVM, there are `FixedOffsetTimeZone.toJavaZoneOffset()` and
* `java.time.ZoneOffset.toKotlinFixedOffsetTimeZone()`
* extension functions to convert between `kotlinx.datetime` and `java.time` objects used for the same purpose.
* Note also the functions available for [TimeZone] in general.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.FixedOffsetTimeZoneSamples.casting
*/
@Serializable(with = FixedOffsetTimeZoneSerializer::class)
public expect class FixedOffsetTimeZone : TimeZone {
/**
* Constructs a time zone with the fixed [offset] from UTC.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.FixedOffsetTimeZoneSamples.constructorFunction
*/
public constructor(offset: UtcOffset)
/**
* The constant offset from UTC that this time zone has.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.FixedOffsetTimeZoneSamples.offset
*/
public val offset: UtcOffset
@Deprecated("Use offset.totalSeconds", ReplaceWith("offset.totalSeconds"))
public val totalSeconds: Int
}
@Deprecated("Use FixedOffsetTimeZone or UtcOffset instead", ReplaceWith("FixedOffsetTimeZone"))
public typealias ZoneOffset = FixedOffsetTimeZone
/**
* Finds the offset from UTC this time zone has at the specified [instant] of physical time.
*
* **Pitfall**: the offset returned from this function should typically not be used for datetime arithmetics
* because the offset can change over time due to daylight-saving-time transitions and other reasons.
* Use [TimeZone] directly with arithmetic operations instead.
*
* @see Instant.toLocalDateTime
* @see TimeZone.offsetAt
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.offsetAt
*/
public expect fun TimeZone.offsetAt(instant: Instant): UtcOffset
/**
* Returns a civil datetime value that this instant has in the specified [timeZone].
*
* Note that while this conversion is unambiguous, the inverse ([LocalDateTime.toInstant])
* is not necessarily so.
*
* @see LocalDateTime.toInstant
* @see Instant.offsetIn
* @throws DateTimeArithmeticException if this value is too large to fit in [LocalDateTime].
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.instantToLocalDateTime
*/
public expect fun Instant.toLocalDateTime(timeZone: TimeZone): LocalDateTime
/**
* Returns a civil datetime value that this instant has in the specified [UTC offset][offset].
*
* **Pitfall**: it is typically more robust to use [TimeZone] directly because the offset can change over time due to
* daylight-saving-time transitions and other reasons, so [this] instant may actually correspond to a different offset
* in the implied time zone.
*
* @see LocalDateTime.toInstant
* @see Instant.offsetIn
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.instantToLocalDateTimeInOffset
*/
internal expect fun Instant.toLocalDateTime(offset: UtcOffset): LocalDateTime
/**
* Finds the offset from UTC the specified [timeZone] has at this instant of physical time.
*
* **Pitfall**: the offset returned from this function should typically not be used for datetime arithmetics
* because the offset can change over time due to daylight-saving-time transitions and other reasons.
* Use [TimeZone] directly with arithmetic operations instead.
*
* @see Instant.toLocalDateTime
* @see TimeZone.offsetAt
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.offsetIn
*/
public fun Instant.offsetIn(timeZone: TimeZone): UtcOffset =
timeZone.offsetAt(this)
/**
* Returns an instant that corresponds to this civil datetime value in the specified [timeZone].
*
* Note that the conversion is not always well-defined. There can be the following possible situations:
* - Only one instant has this datetime value in the [timeZone].
* In this case, the conversion is unambiguous.
* - No instant has this datetime value in the [timeZone].
* Such a situation appears when the time zone experiences a transition from a lesser to a greater offset.
* In this case, the conversion is performed with the lesser (earlier) offset, as if the time gap didn't occur yet.
* - Two possible instants can have these datetime components in the [timeZone].
* In this case, the earlier instant is returned.
*
* @see Instant.toLocalDateTime
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.localDateTimeToInstantInZone
*/
public expect fun LocalDateTime.toInstant(timeZone: TimeZone): Instant
/**
* Returns an instant that corresponds to this civil datetime value that happens at the specified [UTC offset][offset].
*
* @see Instant.toLocalDateTime
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.localDateTimeToInstantInOffset
*/
public expect fun LocalDateTime.toInstant(offset: UtcOffset): Instant
/**
* Returns an instant that corresponds to the start of this date in the specified [timeZone].
*
* Note that it's not equivalent to `atTime(0, 0).toInstant(timeZone)`
* because a day does not always start at a fixed time 00:00:00.
* For example, if, due to daylight saving time, clocks were shifted from 23:30
* of one day directly to 00:30 of the next day, skipping the midnight, then
* `atStartOfDayIn` would return the `Instant` corresponding to 00:30, whereas
* `atTime(0, 0).toInstant(timeZone)` would return the `Instant` corresponding
* to 01:00.
*
* @sample kotlinx.datetime.test.samples.TimeZoneSamples.atStartOfDayIn
*/
public expect fun LocalDate.atStartOfDayIn(timeZone: TimeZone): Instant
internal expect fun localDateTimeToInstant(
dateTime: LocalDateTime, timeZone: TimeZone, preferred: UtcOffset? = null
): Instant