0
# Platform Integration
1
2
Platform-specific extension functions and interoperability with native date/time APIs. The library provides seamless integration with Java Time API (JVM) and Foundation date/time types (Darwin/iOS/macOS).
3
4
## Capabilities
5
6
### JVM Integration
7
8
Bidirectional conversion functions between kotlinx-datetime types and Java Time API types for seamless interoperability on the JVM platform.
9
10
#### LocalDate Conversions
11
12
```kotlin { .api }
13
/**
14
* Convert kotlinx.datetime.LocalDate to java.time.LocalDate
15
* @returns Equivalent java.time.LocalDate
16
*/
17
fun LocalDate.toJavaLocalDate(): java.time.LocalDate
18
19
/**
20
* Convert java.time.LocalDate to kotlinx.datetime.LocalDate
21
* @returns Equivalent kotlinx.datetime.LocalDate
22
*/
23
fun java.time.LocalDate.toKotlinLocalDate(): LocalDate
24
```
25
26
#### LocalTime Conversions
27
28
```kotlin { .api }
29
/**
30
* Convert kotlinx.datetime.LocalTime to java.time.LocalTime
31
* @returns Equivalent java.time.LocalTime
32
*/
33
fun LocalTime.toJavaLocalTime(): java.time.LocalTime
34
35
/**
36
* Convert java.time.LocalTime to kotlinx.datetime.LocalTime
37
* @returns Equivalent kotlinx.datetime.LocalTime
38
*/
39
fun java.time.LocalTime.toKotlinLocalTime(): LocalTime
40
```
41
42
#### LocalDateTime Conversions
43
44
```kotlin { .api }
45
/**
46
* Convert kotlinx.datetime.LocalDateTime to java.time.LocalDateTime
47
* @returns Equivalent java.time.LocalDateTime
48
*/
49
fun LocalDateTime.toJavaLocalDateTime(): java.time.LocalDateTime
50
51
/**
52
* Convert java.time.LocalDateTime to kotlinx.datetime.LocalDateTime
53
* @returns Equivalent kotlinx.datetime.LocalDateTime
54
*/
55
fun java.time.LocalDateTime.toKotlinLocalDateTime(): LocalDateTime
56
```
57
58
#### YearMonth Conversions
59
60
```kotlin { .api }
61
/**
62
* Convert kotlinx.datetime.YearMonth to java.time.YearMonth
63
* @returns Equivalent java.time.YearMonth
64
*/
65
fun YearMonth.toJavaYearMonth(): java.time.YearMonth
66
67
/**
68
* Convert java.time.YearMonth to kotlinx.datetime.YearMonth
69
* @returns Equivalent kotlinx.datetime.YearMonth
70
*/
71
fun java.time.YearMonth.toKotlinYearMonth(): YearMonth
72
```
73
74
**Usage Examples:**
75
76
```kotlin
77
import kotlinx.datetime.*
78
import java.time.LocalDate as JavaLocalDate
79
import java.time.LocalTime as JavaLocalTime
80
import java.time.LocalDateTime as JavaLocalDateTime
81
import java.time.YearMonth as JavaYearMonth
82
83
// Converting from kotlinx-datetime to Java Time
84
val kotlinDate = LocalDate(2023, 12, 25)
85
val kotlinTime = LocalTime(15, 30, 45)
86
val kotlinDateTime = LocalDateTime(kotlinDate, kotlinTime)
87
val kotlinYearMonth = YearMonth(2023, 12)
88
89
val javaDate = kotlinDate.toJavaLocalDate()
90
val javaTime = kotlinTime.toJavaLocalTime()
91
val javaDateTime = kotlinDateTime.toJavaLocalDateTime()
92
val javaYearMonth = kotlinYearMonth.toJavaYearMonth()
93
94
println("Java Date: $javaDate") // 2023-12-25
95
println("Java Time: $javaTime") // 15:30:45
96
println("Java DateTime: $javaDateTime") // 2023-12-25T15:30:45
97
println("Java YearMonth: $javaYearMonth") // 2023-12
98
99
// Converting from Java Time to kotlinx-datetime
100
val backToKotlinDate = javaDate.toKotlinLocalDate()
101
val backToKotlinTime = javaTime.toKotlinLocalTime()
102
val backToKotlinDateTime = javaDateTime.toKotlinLocalDateTime()
103
val backToKotlinYearMonth = javaYearMonth.toKotlinYearMonth()
104
105
// Verify round-trip conversion
106
println("Round-trip date: ${kotlinDate == backToKotlinDate}") // true
107
println("Round-trip time: ${kotlinTime == backToKotlinTime}") // true
108
println("Round-trip dateTime: ${kotlinDateTime == backToKotlinDateTime}") // true
109
println("Round-trip yearMonth: ${kotlinYearMonth == backToKotlinYearMonth}") // true
110
```
111
112
#### Time Zone and Offset Conversions
113
114
```kotlin { .api }
115
/**
116
* Convert kotlinx.datetime.TimeZone to java.time.ZoneId
117
* @returns Equivalent java.time.ZoneId
118
*/
119
fun TimeZone.toJavaZoneId(): java.time.ZoneId
120
121
/**
122
* Convert java.time.ZoneId to kotlinx.datetime.TimeZone
123
* @returns Equivalent kotlinx.datetime.TimeZone
124
*/
125
fun java.time.ZoneId.toKotlinTimeZone(): TimeZone
126
127
/**
128
* Convert kotlinx.datetime.FixedOffsetTimeZone to java.time.ZoneOffset
129
* @returns Equivalent java.time.ZoneOffset
130
*/
131
fun FixedOffsetTimeZone.toJavaZoneOffset(): java.time.ZoneOffset
132
133
/**
134
* Convert java.time.ZoneOffset to kotlinx.datetime.FixedOffsetTimeZone
135
* @returns Equivalent kotlinx.datetime.FixedOffsetTimeZone
136
*/
137
fun java.time.ZoneOffset.toKotlinFixedOffsetTimeZone(): FixedOffsetTimeZone
138
139
/**
140
* Convert kotlinx.datetime.UtcOffset to java.time.ZoneOffset
141
* @returns Equivalent java.time.ZoneOffset
142
*/
143
fun UtcOffset.toJavaZoneOffset(): java.time.ZoneOffset
144
145
/**
146
* Convert java.time.ZoneOffset to kotlinx.datetime.UtcOffset
147
* @returns Equivalent kotlinx.datetime.UtcOffset
148
*/
149
fun java.time.ZoneOffset.toKotlinUtcOffset(): UtcOffset
150
```
151
152
**Usage Examples:**
153
154
```kotlin
155
import kotlinx.datetime.*
156
import java.time.ZoneId
157
import java.time.ZoneOffset
158
159
// Time zone conversions
160
val kotlinTimeZone = TimeZone.of("America/New_York")
161
val javaZoneId = kotlinTimeZone.toJavaZoneId()
162
val backToKotlin = javaZoneId.toKotlinTimeZone()
163
164
println("Kotlin TimeZone: ${kotlinTimeZone.id}") // America/New_York
165
println("Java ZoneId: $javaZoneId") // America/New_York
166
println("Round-trip: ${kotlinTimeZone.id == backToKotlin.id}") // true
167
168
// Offset conversions
169
val kotlinOffset = UtcOffset(hours = -5)
170
val kotlinFixedTz = FixedOffsetTimeZone(kotlinOffset)
171
172
val javaOffset = kotlinOffset.toJavaZoneOffset()
173
val javaOffsetFromFixed = kotlinFixedTz.toJavaZoneOffset()
174
175
println("Kotlin offset: $kotlinOffset") // -05:00
176
println("Java offset: $javaOffset") // -05:00
177
println("From fixed TZ: $javaOffsetFromFixed") // -05:00
178
179
// Convert back
180
val backToKotlinOffset = javaOffset.toKotlinUtcOffset()
181
val backToFixedTz = javaOffset.toKotlinFixedOffsetTimeZone()
182
183
println("Round-trip offset: ${kotlinOffset == backToKotlinOffset}") // true
184
println("Fixed TZ offset: ${backToFixedTz.offset}") // -05:00
185
```
186
187
#### Period Conversions
188
189
```kotlin { .api }
190
/**
191
* Convert kotlinx.datetime.DatePeriod to java.time.Period
192
* @returns Equivalent java.time.Period
193
*/
194
fun DatePeriod.toJavaPeriod(): java.time.Period
195
196
/**
197
* Convert java.time.Period to kotlinx.datetime.DatePeriod
198
* @returns Equivalent kotlinx.datetime.DatePeriod
199
*/
200
fun java.time.Period.toKotlinDatePeriod(): DatePeriod
201
```
202
203
**Usage Examples:**
204
205
```kotlin
206
import kotlinx.datetime.*
207
import java.time.Period as JavaPeriod
208
209
// Period conversions
210
val kotlinPeriod = DatePeriod(years = 1, months = 6, days = 15)
211
val javaPeriod = kotlinPeriod.toJavaPeriod()
212
val backToKotlin = javaPeriod.toKotlinDatePeriod()
213
214
println("Kotlin period: $kotlinPeriod") // P1Y6M15D
215
println("Java period: $javaPeriod") // P1Y6M15D
216
println("Round-trip: ${kotlinPeriod == backToKotlin}") // true
217
218
// Working with Java Period arithmetic
219
val javaDate = JavaLocalDate.of(2023, 1, 1)
220
val resultDate = javaDate.plus(javaPeriod)
221
println("Java result: $resultDate") // 2023-07-16
222
223
// Convert result back to Kotlin
224
val kotlinResult = resultDate.toKotlinLocalDate()
225
println("Kotlin result: $kotlinResult") // 2023-07-16
226
```
227
228
### Darwin (iOS/macOS) Integration
229
230
Conversion functions for interoperability with Foundation's date and time types on Darwin platforms (iOS, macOS, watchOS, tvOS).
231
232
#### NSDateComponents Conversions
233
234
```kotlin { .api }
235
/**
236
* Convert LocalDate to NSDateComponents
237
* @returns NSDateComponents with year, month, and day set
238
*/
239
fun LocalDate.toNSDateComponents(): NSDateComponents
240
241
/**
242
* Convert LocalDateTime to NSDateComponents
243
* @returns NSDateComponents with date and time components set
244
*/
245
fun LocalDateTime.toNSDateComponents(): NSDateComponents
246
247
/**
248
* Convert YearMonth to NSDateComponents
249
* @returns NSDateComponents with year and month set
250
*/
251
fun YearMonth.toNSDateComponents(): NSDateComponents
252
```
253
254
#### NSTimeZone Conversions
255
256
```kotlin { .api }
257
/**
258
* Convert kotlinx.datetime.TimeZone to NSTimeZone
259
* @returns Equivalent NSTimeZone
260
*/
261
fun TimeZone.toNSTimeZone(): NSTimeZone
262
263
/**
264
* Convert NSTimeZone to kotlinx.datetime.TimeZone
265
* @returns Equivalent kotlinx.datetime.TimeZone
266
*/
267
fun NSTimeZone.toKotlinTimeZone(): TimeZone
268
```
269
270
**Usage Examples:**
271
272
```kotlin
273
// Note: This would be used in iOS/macOS code
274
import kotlinx.datetime.*
275
import platform.Foundation.*
276
277
// Convert Kotlin date/time to NSDateComponents
278
val kotlinDate = LocalDate(2023, 12, 25)
279
val kotlinDateTime = LocalDateTime(2023, 12, 25, 15, 30, 45)
280
val kotlinYearMonth = YearMonth(2023, 12)
281
282
val dateComponents = kotlinDate.toNSDateComponents()
283
val dateTimeComponents = kotlinDateTime.toNSDateComponents()
284
val yearMonthComponents = kotlinYearMonth.toNSDateComponents()
285
286
// Access individual components
287
println("Year: ${dateComponents.year}") // 2023
288
println("Month: ${dateComponents.month}") // 12
289
println("Day: ${dateComponents.day}") // 25
290
291
println("Hour: ${dateTimeComponents.hour}") // 15
292
println("Minute: ${dateTimeComponents.minute}") // 30
293
println("Second: ${dateTimeComponents.second}") // 45
294
295
// Time zone conversions
296
val kotlinTimeZone = TimeZone.of("America/New_York")
297
val nsTimeZone = kotlinTimeZone.toNSTimeZone()
298
val backToKotlin = nsTimeZone.toKotlinTimeZone()
299
300
println("Kotlin TZ: ${kotlinTimeZone.id}") // America/New_York
301
println("NS TZ: ${nsTimeZone.name}") // America/New_York
302
println("Round-trip: ${kotlinTimeZone.id == backToKotlin.id}") // true
303
304
// Create NSDate from components
305
val calendar = NSCalendar.currentCalendar
306
val nsDate = calendar.dateFromComponents(dateTimeComponents)
307
308
// Use with iOS/macOS APIs
309
val formatter = NSDateFormatter()
310
formatter.dateStyle = NSDateFormatterLongStyle
311
formatter.timeStyle = NSDateFormatterShortStyle
312
val formatted = formatter.stringFromDate(nsDate!!)
313
println("Formatted: $formatted") // "December 25, 2023 at 3:30 PM" (locale-dependent)
314
```
315
316
## Cross-Platform Usage Patterns
317
318
### Unified Date/Time Handling
319
320
```kotlin
321
import kotlinx.datetime.*
322
323
// Common multiplatform code
324
class EventScheduler {
325
fun createEvent(
326
name: String,
327
date: LocalDate,
328
time: LocalTime,
329
timeZone: TimeZone,
330
duration: DateTimePeriod
331
): ScheduledEvent {
332
val startInstant = date.atTime(time).toInstant(timeZone)
333
val endInstant = startInstant.plus(duration, timeZone)
334
335
return ScheduledEvent(
336
name = name,
337
start = startInstant,
338
end = endInstant,
339
timeZone = timeZone
340
)
341
}
342
}
343
344
data class ScheduledEvent(
345
val name: String,
346
val start: Instant,
347
val end: Instant,
348
val timeZone: TimeZone
349
)
350
351
// Platform-specific implementations
352
expect class PlatformEventIntegration {
353
fun addToSystemCalendar(event: ScheduledEvent)
354
fun showNotification(event: ScheduledEvent, beforeMinutes: Int)
355
}
356
357
// JVM implementation
358
actual class PlatformEventIntegration {
359
actual fun addToSystemCalendar(event: ScheduledEvent) {
360
// Use Java Time API for system integration
361
val javaStartTime = event.start.toLocalDateTime(event.timeZone).toJavaLocalDateTime()
362
val javaEndTime = event.end.toLocalDateTime(event.timeZone).toJavaLocalDateTime()
363
val javaZone = event.timeZone.toJavaZoneId()
364
365
// Integrate with Java calendar APIs
366
// Implementation depends on specific calendar system
367
}
368
369
actual fun showNotification(event: ScheduledEvent, beforeMinutes: Int) {
370
// Use Java notification APIs
371
val notificationTime = event.start.minus(beforeMinutes, DateTimeUnit.MINUTE, event.timeZone)
372
// Schedule notification at notificationTime
373
}
374
}
375
376
// iOS implementation
377
actual class PlatformEventIntegration {
378
actual fun addToSystemCalendar(event: ScheduledEvent) {
379
// Use EventKit framework
380
val startComponents = event.start.toLocalDateTime(event.timeZone).toNSDateComponents()
381
val endComponents = event.end.toLocalDateTime(event.timeZone).toNSDateComponents()
382
val nsTimeZone = event.timeZone.toNSTimeZone()
383
384
startComponents.timeZone = nsTimeZone
385
endComponents.timeZone = nsTimeZone
386
387
// Create EKEvent and add to calendar
388
// Implementation depends on EventKit usage
389
}
390
391
actual fun showNotification(event: ScheduledEvent, beforeMinutes: Int) {
392
// Use UserNotifications framework
393
val notificationTime = event.start.minus(beforeMinutes, DateTimeUnit.MINUTE, event.timeZone)
394
// Schedule UNNotificationRequest at notificationTime
395
}
396
}
397
```
398
399
### Data Persistence Integration
400
401
```kotlin
402
import kotlinx.datetime.*
403
404
// Common data model
405
@Serializable
406
data class Task(
407
val id: String,
408
val title: String,
409
val dueDate: LocalDate,
410
val timeZone: TimeZone,
411
val createdAt: Instant,
412
val priority: Priority
413
)
414
415
enum class Priority { LOW, MEDIUM, HIGH }
416
417
// Platform-specific persistence
418
expect class TaskRepository {
419
suspend fun saveTask(task: Task)
420
suspend fun getTasks(dateRange: LocalDateRange, timeZone: TimeZone): List<Task>
421
suspend fun updateTask(task: Task)
422
suspend fun deleteTask(id: String)
423
}
424
425
// JVM implementation (using SQL database)
426
actual class TaskRepository {
427
actual suspend fun saveTask(task: Task) {
428
// Convert to database-friendly formats
429
val dueDateEpochDays = task.dueDate.toEpochDays()
430
val createdAtEpochSeconds = task.createdAt.epochSeconds
431
val timeZoneId = task.timeZone.id
432
433
// SQL insert using converted values
434
// INSERT INTO tasks (id, title, due_date_epoch_days, timezone_id, created_at_epoch_seconds, priority)
435
// VALUES (?, ?, ?, ?, ?, ?)
436
}
437
438
actual suspend fun getTasks(dateRange: LocalDateRange, timeZone: TimeZone): List<Task> {
439
val startEpochDays = dateRange.start.toEpochDays()
440
val endEpochDays = dateRange.endInclusive.toEpochDays()
441
442
// SQL query with epoch day range
443
// SELECT * FROM tasks WHERE due_date_epoch_days BETWEEN ? AND ?
444
445
// Convert results back to kotlinx-datetime types
446
return emptyList() // Placeholder
447
}
448
449
actual suspend fun updateTask(task: Task) {
450
// Similar conversion and SQL update
451
}
452
453
actual suspend fun deleteTask(id: String) {
454
// SQL delete
455
}
456
}
457
458
// iOS implementation (using Core Data)
459
actual class TaskRepository {
460
actual suspend fun saveTask(task: Task) {
461
// Convert to NSDateComponents for Core Data
462
val dueDateComponents = task.dueDate.toNSDateComponents()
463
val nsTimeZone = task.timeZone.toNSTimeZone()
464
465
// Create NSManagedObject with converted values
466
// Set Core Data attributes using NSDateComponents
467
}
468
469
actual suspend fun getTasks(dateRange: LocalDateRange, timeZone: TimeZone): List<Task> {
470
// Convert range to NSDateComponents for Core Data predicate
471
val startComponents = dateRange.start.toNSDateComponents()
472
val endComponents = dateRange.endInclusive.toNSDateComponents()
473
474
// Create NSPredicate for date range query
475
// Fetch NSManagedObjects and convert back to Task instances
476
477
return emptyList() // Placeholder
478
}
479
480
actual suspend fun updateTask(task: Task) {
481
// Core Data update with NSDateComponents
482
}
483
484
actual suspend fun deleteTask(id: String) {
485
// Core Data delete
486
}
487
}
488
```
489
490
### Legacy Code Integration
491
492
```kotlin
493
import kotlinx.datetime.*
494
495
// Wrapper for legacy Java Date APIs
496
class LegacyDateAdapter {
497
498
// Convert from legacy java.util.Date
499
fun fromLegacyDate(legacyDate: java.util.Date): Instant {
500
// java.util.Date -> java.time.Instant -> kotlin.time.Instant
501
return legacyDate.toInstant().let { javaInstant ->
502
Instant.fromEpochSeconds(javaInstant.epochSecond, javaInstant.nano.toLong())
503
}
504
}
505
506
// Convert to legacy java.util.Date
507
fun toLegacyDate(instant: Instant): java.util.Date {
508
return java.util.Date.from(
509
java.time.Instant.ofEpochSecond(instant.epochSeconds, instant.nanosecondsOfSecond.toLong())
510
)
511
}
512
513
// Convert from legacy java.util.Calendar
514
fun fromLegacyCalendar(calendar: java.util.Calendar, timeZone: TimeZone): LocalDateTime {
515
val javaLocalDateTime = java.time.LocalDateTime.of(
516
calendar.get(java.util.Calendar.YEAR),
517
calendar.get(java.util.Calendar.MONTH) + 1, // Calendar months are 0-based
518
calendar.get(java.util.Calendar.DAY_OF_MONTH),
519
calendar.get(java.util.Calendar.HOUR_OF_DAY),
520
calendar.get(java.util.Calendar.MINUTE),
521
calendar.get(java.util.Calendar.SECOND),
522
calendar.get(java.util.Calendar.MILLISECOND) * 1_000_000
523
)
524
return javaLocalDateTime.toKotlinLocalDateTime()
525
}
526
527
// Convert to legacy java.util.Calendar
528
fun toLegacyCalendar(dateTime: LocalDateTime, timeZone: TimeZone): java.util.Calendar {
529
val calendar = java.util.Calendar.getInstance(timeZone.toJavaZoneId().let {
530
java.util.TimeZone.getTimeZone(it)
531
})
532
533
calendar.set(java.util.Calendar.YEAR, dateTime.year)
534
calendar.set(java.util.Calendar.MONTH, dateTime.monthNumber - 1) // Calendar months are 0-based
535
calendar.set(java.util.Calendar.DAY_OF_MONTH, dateTime.dayOfMonth)
536
calendar.set(java.util.Calendar.HOUR_OF_DAY, dateTime.hour)
537
calendar.set(java.util.Calendar.MINUTE, dateTime.minute)
538
calendar.set(java.util.Calendar.SECOND, dateTime.second)
539
calendar.set(java.util.Calendar.MILLISECOND, dateTime.nanosecond / 1_000_000)
540
541
return calendar
542
}
543
}
544
545
// Usage with legacy systems
546
class LegacySystemIntegration {
547
private val adapter = LegacyDateAdapter()
548
549
fun processLegacyData(legacyDate: java.util.Date, legacyCalendar: java.util.Calendar) {
550
// Convert legacy types to kotlinx-datetime
551
val instant = adapter.fromLegacyDate(legacyDate)
552
val localDateTime = adapter.fromLegacyCalendar(legacyCalendar, TimeZone.currentSystemDefault())
553
554
// Perform modern date/time operations
555
val tomorrow = instant.plus(1, DateTimeUnit.DAY, TimeZone.UTC)
556
val nextWeek = localDateTime.date.plus(1, DateTimeUnit.WEEK)
557
558
// Convert back to legacy formats if needed
559
val legacyTomorrow = adapter.toLegacyDate(tomorrow)
560
val legacyNextWeek = adapter.toLegacyCalendar(
561
nextWeek.atTime(localDateTime.time),
562
TimeZone.currentSystemDefault()
563
)
564
565
// Use with legacy APIs
566
println("Legacy tomorrow: $legacyTomorrow")
567
println("Legacy next week: ${legacyNextWeek.time}")
568
}
569
}
570
```
571
572
## Platform-Specific Optimizations
573
574
### JVM Performance Optimizations
575
576
```kotlin
577
import kotlinx.datetime.*
578
import java.time.format.DateTimeFormatter
579
import java.util.concurrent.ConcurrentHashMap
580
581
// Leverage Java Time performance characteristics
582
class OptimizedJvmDateOperations {
583
584
// Cache frequently used formatters
585
private val formatterCache = ConcurrentHashMap<String, DateTimeFormatter>()
586
587
fun formatWithCaching(dateTime: LocalDateTime, pattern: String): String {
588
val formatter = formatterCache.computeIfAbsent(pattern) {
589
DateTimeFormatter.ofPattern(it)
590
}
591
592
return dateTime.toJavaLocalDateTime().format(formatter)
593
}
594
595
// Bulk operations using Java streams
596
fun processDateRange(range: LocalDateRange, processor: (LocalDate) -> String): List<String> {
597
return range.asSequence()
598
.map { it.toJavaLocalDate() } // Convert once
599
.map { javaDate -> processor(javaDate.toKotlinLocalDate()) }
600
.toList()
601
}
602
603
// Efficient time zone operations
604
private val timeZoneCache = ConcurrentHashMap<String, java.time.ZoneId>()
605
606
fun getOptimizedTimeZone(zoneId: String): TimeZone {
607
val javaZone = timeZoneCache.computeIfAbsent(zoneId) {
608
java.time.ZoneId.of(it)
609
}
610
return javaZone.toKotlinTimeZone()
611
}
612
}
613
```
614
615
### iOS/Darwin Optimizations
616
617
```kotlin
618
// iOS-specific optimizations
619
class OptimizedDarwinDateOperations {
620
621
// Use NSCalendar for efficient bulk operations
622
fun calculateBusinessDays(start: LocalDate, end: LocalDate): Int {
623
val calendar = NSCalendar.currentCalendar
624
val startComponents = start.toNSDateComponents()
625
val endComponents = end.toNSDateComponents()
626
627
val startDate = calendar.dateFromComponents(startComponents)!!
628
val endDate = calendar.dateFromComponents(endComponents)!!
629
630
// Use NSCalendar's efficient date enumeration
631
var businessDays = 0
632
calendar.enumerateDatesStartingAfterDate(
633
startDate,
634
matchingComponents = NSDateComponents().apply { day = 1 },
635
options = 0u
636
) { date, _, stop ->
637
if (date != null && date <= endDate) {
638
val weekday = calendar.component(NSCalendarUnitWeekday, fromDate = date).toInt()
639
if (weekday != 1 && weekday != 7) { // Not Sunday or Saturday
640
businessDays++
641
}
642
} else {
643
stop.value = true
644
}
645
}
646
647
return businessDays
648
}
649
650
// Efficient time zone aware conversions
651
fun convertToSystemCalendar(events: List<ScheduledEvent>) {
652
val calendar = NSCalendar.currentCalendar
653
654
events.forEach { event ->
655
val components = event.start.toLocalDateTime(event.timeZone).toNSDateComponents()
656
components.timeZone = event.timeZone.toNSTimeZone()
657
658
// Batch calendar operations for efficiency
659
val systemDate = calendar.dateFromComponents(components)
660
// Add to system calendar in batch
661
}
662
}
663
}
664
```