@@ -37,12 +37,18 @@ internal data class CalendarAddRequest(
3737 val startMs : Long ,
3838 val endMs : Long ,
3939 val isAllDay : Boolean ,
40+ val timeZoneId : String ,
4041 val location : String? ,
4142 val notes : String? ,
4243 val calendarId : Long? ,
4344 val calendarTitle : String? ,
4445)
4546
47+ private data class CalendarAddRange (
48+ val start : Instant ,
49+ val end : Instant ,
50+ )
51+
4652/* *
4753 * Normalized calendar event returned through gateway calendar commands.
4854 */
@@ -148,7 +154,7 @@ private object SystemCalendarDataSource : CalendarDataSource {
148154 put(CalendarContract .Events .DTSTART , request.startMs)
149155 put(CalendarContract .Events .DTEND , request.endMs)
150156 put(CalendarContract .Events .ALL_DAY , if (request.isAllDay) 1 else 0 )
151- put(CalendarContract .Events .EVENT_TIMEZONE , TimeZone .getDefault().id )
157+ put(CalendarContract .Events .EVENT_TIMEZONE , request.timeZoneId )
152158 request.location?.let { put(CalendarContract .Events .EVENT_LOCATION , it) }
153159 request.notes?.let { put(CalendarContract .Events .DESCRIPTION , it) }
154160 }
@@ -393,18 +399,36 @@ class CalendarHandler private constructor(
393399 val end =
394400 parseISO((params[" endISO" ] as ? JsonPrimitive )?.content)
395401 ? : return null
402+ val isAllDay = (params[" isAllDay" ] as ? JsonPrimitive )?.content?.toBooleanStrictOrNull() ? : false
403+ val addRange = normalizeAddRange(start, end, isAllDay)
396404 return CalendarAddRequest (
397405 title = (params[" title" ] as ? JsonPrimitive )?.content?.trim().orEmpty(),
398- startMs = start.toEpochMilli(),
399- endMs = end.toEpochMilli(),
400- isAllDay = (params[" isAllDay" ] as ? JsonPrimitive )?.content?.toBooleanStrictOrNull() ? : false ,
406+ startMs = addRange.start.toEpochMilli(),
407+ endMs = addRange.end.toEpochMilli(),
408+ isAllDay = isAllDay,
409+ timeZoneId = if (isAllDay) " UTC" else TimeZone .getDefault().id,
401410 location = (params[" location" ] as ? JsonPrimitive )?.content?.trim()?.ifEmpty { null },
402411 notes = (params[" notes" ] as ? JsonPrimitive )?.content?.trim()?.ifEmpty { null },
403412 calendarId = (params[" calendarId" ] as ? JsonPrimitive )?.content?.toLongOrNull(),
404413 calendarTitle = (params[" calendarTitle" ] as ? JsonPrimitive )?.content?.trim()?.ifEmpty { null },
405414 )
406415 }
407416
417+ private fun normalizeAddRange (
418+ start : Instant ,
419+ end : Instant ,
420+ isAllDay : Boolean ,
421+ ): CalendarAddRange {
422+ if (! isAllDay) return CalendarAddRange (start = start, end = end)
423+ if (end <= start) return CalendarAddRange (start = start, end = end)
424+ val dayStart = start.truncatedTo(ChronoUnit .DAYS )
425+ val dayEnd = end.truncatedTo(ChronoUnit .DAYS )
426+ return CalendarAddRange (
427+ start = dayStart,
428+ end = if (dayEnd > dayStart) dayEnd else dayStart.plus(1 , ChronoUnit .DAYS ),
429+ )
430+ }
431+
408432 private fun parseISO (raw : String? ): Instant ? {
409433 val value = raw?.trim().orEmpty()
410434 if (value.isEmpty()) return null
0 commit comments