0
# Time Zones and Offsets
1
2
Time zone handling with support for named IANA time zones, fixed UTC offsets, and time zone conversions. The library distinguishes between time zones (which have rules for daylight saving time) and fixed offsets (which are constant).
3
4
## Capabilities
5
6
### TimeZone
7
8
Base class for time zone representations, supporting both named time zones with DST rules and fixed offset time zones.
9
10
```kotlin { .api }
11
/**
12
* Time zone with rules for UTC offset calculations
13
* Base class for all time zone implementations
14
*/
15
expect open class TimeZone {
16
/** Time zone identifier (e.g., "America/New_York", "+05:00") */
17
val id: String
18
19
companion object {
20
/**
21
* Create a time zone from IANA identifier
22
* @param zoneId IANA time zone ID (e.g., "America/New_York", "Europe/London")
23
* @returns TimeZone for the specified identifier
24
* @throws IllegalTimeZoneException if the zone ID is invalid
25
*/
26
fun of(zoneId: String): TimeZone
27
28
/**
29
* Get the current system default time zone
30
* @returns TimeZone representing the system's default time zone
31
*/
32
fun currentSystemDefault(): TimeZone
33
34
/** UTC time zone (equivalent to FixedOffsetTimeZone(UtcOffset.ZERO)) */
35
val UTC: FixedOffsetTimeZone
36
37
/** Set of all available time zone IDs */
38
val availableZoneIds: Set<String>
39
}
40
}
41
```
42
43
**Usage Examples:**
44
45
```kotlin
46
import kotlinx.datetime.*
47
48
// Create named time zones
49
val newYork = TimeZone.of("America/New_York")
50
val london = TimeZone.of("Europe/London")
51
val tokyo = TimeZone.of("Asia/Tokyo")
52
53
// System time zone
54
val systemTz = TimeZone.currentSystemDefault()
55
56
// UTC time zone
57
val utc = TimeZone.UTC
58
59
// List available time zones
60
val allZones = TimeZone.availableZoneIds
61
println("Available zones: ${allZones.size}")
62
allZones.filter { it.startsWith("America/") }.forEach { println(it) }
63
```
64
65
### FixedOffsetTimeZone
66
67
Time zone implementation with a constant UTC offset, useful for representing fixed offsets that don't change with daylight saving time.
68
69
```kotlin { .api }
70
/**
71
* Time zone with constant UTC offset
72
* Extends TimeZone with a fixed, unchanging offset from UTC
73
*/
74
expect class FixedOffsetTimeZone : TimeZone {
75
/** Create a fixed offset time zone */
76
constructor(offset: UtcOffset)
77
78
/** The constant offset from UTC */
79
val offset: UtcOffset
80
}
81
```
82
83
**Usage Examples:**
84
85
```kotlin
86
import kotlinx.datetime.*
87
88
// Create fixed offset time zones
89
val plus5 = FixedOffsetTimeZone(UtcOffset(hours = 5))
90
val minus8 = FixedOffsetTimeZone(UtcOffset(hours = -8))
91
val plus530 = FixedOffsetTimeZone(UtcOffset(hours = 5, minutes = 30))
92
93
println("ID: ${plus5.id}") // "+05:00"
94
println("Offset: ${plus5.offset}") // +05:00
95
```
96
97
### UtcOffset
98
99
Represents a fixed offset from UTC, measured in hours, minutes, and seconds.
100
101
```kotlin { .api }
102
/**
103
* Fixed offset from UTC
104
* Represents a constant time difference from Coordinated Universal Time
105
*/
106
expect class UtcOffset : Comparable<UtcOffset> {
107
/** Total offset in seconds (can be negative for westward offsets) */
108
val totalSeconds: Int
109
110
companion object {
111
/** Zero offset (UTC) */
112
val ZERO: UtcOffset
113
114
/**
115
* Parse UtcOffset from string using specified format
116
* @param input String to parse (e.g., "+05:30", "Z", "-08:00")
117
* @param format Format to use for parsing
118
* @returns Parsed UtcOffset
119
*/
120
fun parse(input: CharSequence, format: DateTimeFormat<UtcOffset>): UtcOffset
121
}
122
}
123
```
124
125
**Factory Functions:**
126
127
```kotlin { .api }
128
/**
129
* Create UtcOffset from components
130
* @param hours Hours component (can be null)
131
* @param minutes Minutes component (can be null)
132
* @param seconds Seconds component (can be null)
133
* @returns UtcOffset representing the total offset
134
*/
135
fun UtcOffset(hours: Int? = null, minutes: Int? = null, seconds: Int? = null): UtcOffset
136
137
/**
138
* Create zero offset (equivalent to UtcOffset.ZERO)
139
* @returns UtcOffset representing UTC (zero offset)
140
*/
141
fun UtcOffset(): UtcOffset
142
```
143
144
**Conversions:**
145
146
```kotlin { .api }
147
/**
148
* Convert this offset to a FixedOffsetTimeZone
149
* @returns FixedOffsetTimeZone with this offset
150
*/
151
fun UtcOffset.asTimeZone(): FixedOffsetTimeZone
152
```
153
154
**Formatting:**
155
156
```kotlin { .api }
157
/**
158
* Format this offset using the specified format
159
* @param format Format to use
160
* @returns Formatted string representation
161
*/
162
fun UtcOffset.format(format: DateTimeFormat<UtcOffset>): String
163
164
/**
165
* Convert to ISO 8601 string representation
166
* @returns ISO format string (e.g., "+05:30", "Z", "-08:00")
167
*/
168
override fun UtcOffset.toString(): String
169
```
170
171
**Usage Examples:**
172
173
```kotlin
174
import kotlinx.datetime.*
175
176
// Create offsets
177
val utc = UtcOffset.ZERO // +00:00 (or "Z")
178
val plus5 = UtcOffset(hours = 5) // +05:00
179
val minus8 = UtcOffset(hours = -8) // -08:00
180
val plus530 = UtcOffset(hours = 5, minutes = 30) // +05:30
181
val complex = UtcOffset(hours = -4, minutes = -30, seconds = -15) // -04:30:15
182
183
// Properties
184
println("Total seconds: ${plus530.totalSeconds}") // 19800
185
186
// Convert to time zone
187
val fixedTz = plus530.asTimeZone()
188
189
// Formatting
190
println("Default: $plus530") // +05:30
191
println("ISO: ${plus530.format(UtcOffset.Formats.ISO)}")
192
```
193
194
### Time Zone Operations
195
196
Extension functions for working with time zones and instants.
197
198
```kotlin { .api }
199
/**
200
* Get the UTC offset for the specified instant in this time zone
201
* @param instant The instant to check the offset for
202
* @returns UtcOffset that applies at the given instant in this time zone
203
*/
204
fun TimeZone.offsetAt(instant: Instant): UtcOffset
205
```
206
207
**Usage Examples:**
208
209
```kotlin
210
import kotlinx.datetime.*
211
import kotlin.time.Clock
212
213
val now = Clock.System.now()
214
val newYork = TimeZone.of("America/New_York")
215
216
// Get current offset (accounts for DST)
217
val currentOffset = newYork.offsetAt(now)
218
println("NY offset now: $currentOffset") // Could be -05:00 or -04:00 depending on DST
219
220
// Check offset at different times of year
221
val winter = LocalDate(2023, 1, 15).atStartOfDayIn(TimeZone.UTC)
222
val summer = LocalDate(2023, 7, 15).atStartOfDayIn(TimeZone.UTC)
223
224
val winterOffset = newYork.offsetAt(winter) // -05:00 (EST)
225
val summerOffset = newYork.offsetAt(summer) // -04:00 (EDT)
226
```
227
228
### Context Receivers for Time Zone Operations
229
230
Advanced time zone conversion functions using context receivers for cleaner API usage.
231
232
```kotlin { .api }
233
/**
234
* Context receiver functions for Instant conversions
235
* These allow calling conversion functions directly on Instant with TimeZone context
236
*/
237
context(TimeZone)
238
fun Instant.toLocalDateTime(): LocalDateTime
239
240
context(TimeZone)
241
fun Instant.offsetIn(): UtcOffset
242
243
context(TimeZone)
244
fun Instant.plus(period: DateTimePeriod): Instant
245
246
context(TimeZone)
247
fun Instant.minus(period: DateTimePeriod): Instant
248
```
249
250
**Usage Examples:**
251
252
```kotlin
253
import kotlinx.datetime.*
254
import kotlin.time.Clock
255
256
val now = Clock.System.now()
257
val timeZone = TimeZone.of("Europe/Paris")
258
259
// Using context receivers (if supported)
260
with(timeZone) {
261
val localTime = now.toLocalDateTime()
262
val offset = now.offsetIn()
263
val tomorrow = now.plus(DatePeriod(days = 1))
264
}
265
```
266
267
## Predefined Formats
268
269
UtcOffset provides several predefined formatting options:
270
271
```kotlin { .api }
272
object UtcOffset.Formats {
273
/** ISO 8601 extended format: +HH:MM, +HH:MM:SS, or Z */
274
val ISO: DateTimeFormat<UtcOffset>
275
276
/** ISO 8601 basic format: +HHMM, +HHMMSS, or Z */
277
val ISO_BASIC: DateTimeFormat<UtcOffset>
278
279
/** Four digits format: always ±HHMM, never Z */
280
val FOUR_DIGITS: DateTimeFormat<UtcOffset>
281
}
282
```
283
284
**Usage Examples:**
285
286
```kotlin
287
import kotlinx.datetime.*
288
289
val offset = UtcOffset(hours = 5, minutes = 30)
290
291
println("ISO: ${offset.format(UtcOffset.Formats.ISO)}") // +05:30
292
println("Basic: ${offset.format(UtcOffset.Formats.ISO_BASIC)}") // +0530
293
println("Four digits: ${offset.format(UtcOffset.Formats.FOUR_DIGITS)}") // +0530
294
295
val utc = UtcOffset.ZERO
296
println("UTC ISO: ${utc.format(UtcOffset.Formats.ISO)}") // Z
297
println("UTC Four digits: ${utc.format(UtcOffset.Formats.FOUR_DIGITS)}") // +0000
298
```
299
300
## Common Time Zone Patterns
301
302
### Working with DST Transitions
303
304
```kotlin
305
import kotlinx.datetime.*
306
307
val newYork = TimeZone.of("America/New_York")
308
309
// Spring forward transition (2023-03-12 02:00 -> 03:00)
310
val beforeSpring = LocalDateTime(2023, 3, 12, 1, 30).toInstant(newYork)
311
val afterSpring = LocalDateTime(2023, 3, 12, 3, 30).toInstant(newYork)
312
313
println("Before spring DST: ${newYork.offsetAt(beforeSpring)}") // -05:00
314
println("After spring DST: ${newYork.offsetAt(afterSpring)}") // -04:00
315
316
// Fall back transition (2023-11-05 02:00 -> 01:00)
317
val beforeFall = LocalDateTime(2023, 11, 5, 0, 30).toInstant(newYork)
318
val afterFall = LocalDateTime(2023, 11, 5, 3, 30).toInstant(newYork)
319
320
println("Before fall DST: ${newYork.offsetAt(beforeFall)}") // -04:00
321
println("After fall DST: ${newYork.offsetAt(afterFall)}") // -05:00
322
```
323
324
### Converting Between Time Zones
325
326
```kotlin
327
import kotlinx.datetime.*
328
import kotlin.time.Clock
329
330
val now = Clock.System.now()
331
332
// Convert the same instant to different time zones
333
val newYork = TimeZone.of("America/New_York")
334
val london = TimeZone.of("Europe/London")
335
val tokyo = TimeZone.of("Asia/Tokyo")
336
337
val nyTime = now.toLocalDateTime(newYork)
338
val londonTime = now.toLocalDateTime(london)
339
val tokyoTime = now.toLocalDateTime(tokyo)
340
341
println("Same moment in different zones:")
342
println("New York: $nyTime")
343
println("London: $londonTime")
344
println("Tokyo: $tokyoTime")
345
```
346
347
### Working with Fixed Offsets
348
349
```kotlin
350
import kotlinx.datetime.*
351
352
// Create a meeting time in a specific offset
353
val meetingTime = LocalDateTime(2023, 12, 25, 15, 30)
354
val offset = UtcOffset(hours = -5) // EST
355
356
val meetingInstant = meetingTime.toInstant(offset)
357
358
// Convert to different time zones
359
val londonTime = meetingInstant.toLocalDateTime(TimeZone.of("Europe/London"))
360
val tokyoTime = meetingInstant.toLocalDateTime(TimeZone.of("Asia/Tokyo"))
361
362
println("Meeting at $meetingTime (UTC$offset):")
363
println("London: $londonTime")
364
println("Tokyo: $tokyoTime")
365
```
366
367
## Error Handling
368
369
```kotlin
370
import kotlinx.datetime.*
371
372
try {
373
val invalidZone = TimeZone.of("Invalid/Zone")
374
} catch (e: IllegalTimeZoneException) {
375
println("Invalid time zone: ${e.message}")
376
}
377
378
// Check if a zone ID is valid before using
379
val zoneId = "America/New_York"
380
if (zoneId in TimeZone.availableZoneIds) {
381
val timeZone = TimeZone.of(zoneId)
382
// Use the time zone safely
383
} else {
384
println("Time zone $zoneId is not available")
385
}
386
```