@@ -179,12 +179,13 @@ public struct ICalendarClient: Sendable {
179179 duration: ICalDuration ? = nil ,
180180 location: String ? = nil ,
181181 description: String ? = nil ,
182- uid: String ? = nil
182+ uid: String ? = nil ,
183+ timeZone: TimeZone = . current
183184 ) -> ICalEvent {
184185 var event = ICalEvent ( uid: uid ?? UUID ( ) . uuidString, summary: summary)
185186
186- event. dateTimeStamp = ICalDateTime ( date: Date ( ) )
187- event. dateTimeStart = ICalDateTime ( date: startDate)
187+ event. dateTimeStamp = ICalDateTime ( date: Date ( ) , timeZone : timeZone )
188+ event. dateTimeStart = ICalDateTime ( date: startDate, timeZone : timeZone )
188189
189190 if let endDate = endDate {
190191 event. dateTimeEnd = ICalDateTime ( date: endDate)
@@ -209,12 +210,13 @@ public struct ICalendarClient: Sendable {
209210 date: Date ,
210211 location: String ? = nil ,
211212 description: String ? = nil ,
212- uid: String ? = nil
213+ uid: String ? = nil ,
214+ timeZone: TimeZone = . current
213215 ) -> ICalEvent {
214216 var event = ICalEvent ( uid: uid ?? UUID ( ) . uuidString, summary: summary)
215217
216- event. dateTimeStamp = ICalDateTime ( date: Date ( ) )
217- event. dateTimeStart = ICalDateTime ( date: date, isDateOnly: true )
218+ event. dateTimeStamp = ICalDateTime ( date: Date ( ) , timeZone : timeZone )
219+ event. dateTimeStart = ICalDateTime ( date: date, timeZone : timeZone , isDateOnly: true )
218220
219221 if let location = location {
220222 event. location = location
@@ -235,15 +237,17 @@ public struct ICalendarClient: Sendable {
235237 recurrenceRule: ICalRecurrenceRule ,
236238 location: String ? = nil ,
237239 description: String ? = nil ,
238- uid: String ? = nil
240+ uid: String ? = nil ,
241+ timeZone: TimeZone = . current
239242 ) -> ICalEvent {
240243 var event = createEvent (
241244 summary: summary,
242245 startDate: startDate,
243246 endDate: endDate,
244247 location: location,
245248 description: description,
246- uid: uid
249+ uid: uid,
250+ timeZone: timeZone
247251 )
248252
249253 event. recurrenceRule = recurrenceRule
@@ -258,14 +262,15 @@ public struct ICalendarClient: Sendable {
258262 dueDate: Date ? = nil ,
259263 priority: Int ? = nil ,
260264 description: String ? = nil ,
261- uid: String ? = nil
265+ uid: String ? = nil ,
266+ timeZone: TimeZone = . current
262267 ) -> ICalTodo {
263268 var todo = ICalTodo ( uid: uid ?? UUID ( ) . uuidString, summary: summary)
264269
265- todo. dateTimeStamp = ICalDateTime ( date: Date ( ) )
270+ todo. dateTimeStamp = ICalDateTime ( date: Date ( ) , timeZone : timeZone )
266271
267272 if let dueDate = dueDate {
268- todo. dueDate = ICalDateTime ( date: dueDate)
273+ todo. dueDate = ICalDateTime ( date: dueDate, timeZone : timeZone )
269274 }
270275
271276 if let priority = priority {
@@ -286,17 +291,19 @@ public struct ICalendarClient: Sendable {
286291 dueDate: Date ? = nil ,
287292 priority: Int ? = nil ,
288293 description: String ? = nil ,
289- uid: String ? = nil
294+ uid: String ? = nil ,
295+ timeZone: TimeZone = . current
290296 ) -> ICalTodo {
291297 var todo = createTodo (
292298 summary: summary,
293299 dueDate: dueDate,
294300 priority: priority,
295301 description: description,
296- uid: uid
302+ uid: uid,
303+ timeZone: timeZone
297304 )
298305
299- todo. dateTimeStart = ICalDateTime ( date: startDate)
306+ todo. dateTimeStart = ICalDateTime ( date: startDate, timeZone : timeZone )
300307 return todo
301308 }
302309
@@ -394,14 +401,15 @@ public struct ICalendarClient: Sendable {
394401 interval: Int = 1 ,
395402 daysOfWeek: [ ICalWeekday ] = [ ] ,
396403 count: Int ? = nil ,
397- until: Date ? = nil
404+ until: Date ? = nil ,
405+ timeZone: TimeZone = . current
398406 ) -> ICalRecurrenceRule {
399407 let byDay = daysOfWeek. isEmpty ? nil : daysOfWeek. map { $0. rawValue }
400408 return ICalRecurrenceRule (
401409 frequency: . weekly,
402410 interval: interval,
403411 count: count,
404- until: until. map { ICalDateTime ( date: $0) } ,
412+ until: until. map { ICalDateTime ( date: $0, timeZone : timeZone ) } ,
405413 byDay: byDay
406414 )
407415 }
@@ -413,7 +421,8 @@ public struct ICalendarClient: Sendable {
413421 weekdayOrdinal: Int ? = nil ,
414422 weekday: ICalWeekday ? = nil ,
415423 count: Int ? = nil ,
416- until: Date ? = nil
424+ until: Date ? = nil ,
425+ timeZone: TimeZone = . current
417426 ) -> ICalRecurrenceRule {
418427 var byMonthDay : [ Int ] ? = nil
419428 var byDay : [ String ] ? = nil
@@ -428,7 +437,7 @@ public struct ICalendarClient: Sendable {
428437 frequency: . monthly,
429438 interval: interval,
430439 count: count,
431- until: until. map { ICalDateTime ( date: $0) } ,
440+ until: until. map { ICalDateTime ( date: $0, timeZone : timeZone ) } ,
432441 byDay: byDay,
433442 byMonthDay: byMonthDay
434443 )
@@ -440,13 +449,14 @@ public struct ICalendarClient: Sendable {
440449 month: Int ? = nil ,
441450 dayOfMonth: Int ? = nil ,
442451 count: Int ? = nil ,
443- until: Date ? = nil
452+ until: Date ? = nil ,
453+ timeZone: TimeZone = . current
444454 ) -> ICalRecurrenceRule {
445455 ICalRecurrenceRule (
446456 frequency: . yearly,
447457 interval: interval,
448458 count: count,
449- until: until. map { ICalDateTime ( date: $0) } ,
459+ until: until. map { ICalDateTime ( date: $0, timeZone : timeZone ) } ,
450460 byMonthDay: dayOfMonth. map { [ $0] } ,
451461 byMonth: month. map { [ $0] }
452462 )
@@ -523,7 +533,8 @@ public struct ICalendarClient: Sendable {
523533 public func updateEvent(
524534 in calendar: inout ICalendar ,
525535 eventUID: String ,
526- updateBlock: ( inout ICalEvent ) -> Void
536+ updateBlock: ( inout ICalEvent ) -> Void ,
537+ timeZone: TimeZone = . current
527538 ) -> Bool {
528539 guard let eventIndex = calendar. events. firstIndex ( where: { $0. uid == eventUID } ) else {
529540 return false
@@ -537,7 +548,7 @@ public struct ICalendarClient: Sendable {
537548 event. sequence = currentSequence + 1
538549
539550 // Update last modified timestamp
540- event. lastModified = ICalDateTime ( date: Date . now)
551+ event. lastModified = ICalDateTime ( date: Date . now, timeZone : timeZone )
541552
542553 // Update the event in the calendar
543554 calendar. components [
@@ -668,15 +679,16 @@ public struct ICalendarClient: Sendable {
668679 public func findEventsWithUpcomingAlarms(
669680 in calendar: ICalendar ,
670681 within timeInterval: TimeInterval ,
671- from referenceDate: Date = Date ( )
682+ from referenceDate: Date = Date ( ) ,
683+ timeZone: TimeZone = . current
672684 ) -> [ ( event: ICalEvent , alarm: ICalAlarm , triggerDate: Date ) ] {
673685 var upcomingAlarms : [ ( event: ICalEvent , alarm: ICalAlarm , triggerDate: Date ) ] = [ ]
674686
675687 for event in calendar. events {
676688 guard let eventStart = event. dateTimeStart? . date else { continue }
677689
678690 for alarm in event. alarms {
679- if let triggerDate = calculateAlarmTriggerDate ( alarm: alarm, eventStart: eventStart) {
691+ if let triggerDate = calculateAlarmTriggerDate ( alarm: alarm, eventStart: eventStart, timeZone : timeZone ) {
680692 let timeDifference = triggerDate. timeIntervalSince ( referenceDate)
681693 if timeDifference >= 0 && timeDifference <= timeInterval {
682694 upcomingAlarms. append (
@@ -691,7 +703,7 @@ public struct ICalendarClient: Sendable {
691703 }
692704
693705 /// Calculate when an alarm will trigger based on the event start time
694- private func calculateAlarmTriggerDate( alarm: ICalAlarm , eventStart: Date ) -> Date ? {
706+ private func calculateAlarmTriggerDate( alarm: ICalAlarm , eventStart: Date , timeZone : TimeZone = . current ) -> Date ? {
695707 guard let trigger = alarm. trigger else { return nil }
696708
697709 // Handle duration-based triggers (e.g., "-PT15M" for 15 minutes before)
@@ -703,7 +715,7 @@ public struct ICalendarClient: Sendable {
703715 }
704716
705717 // Handle absolute date-time triggers
706- if let absoluteDate = ICalendarFormatter . parseDateTime ( trigger) {
718+ if let absoluteDate = ICalendarFormatter . parseDateTime ( trigger, timeZone : timeZone ) {
707719 return absoluteDate. date
708720 }
709721
@@ -718,7 +730,8 @@ public struct ICalendarClient: Sendable {
718730 eventUID: String ,
719731 newStartDate: Date ,
720732 newEndDate: Date ? = nil ,
721- keepDuration: Bool = true
733+ keepDuration: Bool = true ,
734+ timeZone: TimeZone = . current
722735 ) -> Bool {
723736 updateEvent ( in: & calendar, eventUID: eventUID) { event in
724737 let originalDuration : TimeInterval ?
@@ -731,12 +744,12 @@ public struct ICalendarClient: Sendable {
731744 originalDuration = nil
732745 }
733746
734- event. dateTimeStart = ICalDateTime ( date: newStartDate)
747+ event. dateTimeStart = ICalDateTime ( date: newStartDate, timeZone : timeZone )
735748
736749 if let newEndDate = newEndDate {
737- event. dateTimeEnd = ICalDateTime ( date: newEndDate)
750+ event. dateTimeEnd = ICalDateTime ( date: newEndDate, timeZone : timeZone )
738751 } else if let duration = originalDuration {
739- event. dateTimeEnd = ICalDateTime ( date: newStartDate. addingTimeInterval ( duration) )
752+ event. dateTimeEnd = ICalDateTime ( date: newStartDate. addingTimeInterval ( duration) , timeZone : timeZone )
740753 }
741754 }
742755 }
@@ -875,7 +888,9 @@ extension ICalendarClient {
875888 description: String ? = nil ,
876889 organizer: ICalAttendee ,
877890 attendees: [ ICalAttendee ] ,
878- reminderMinutes: Int ? = nil
891+ reminderMinutes: Int ? = nil ,
892+ timeZone: TimeZone = . current,
893+ uid: String = UUID ( ) . uuidString
879894 ) -> ICalendar {
880895 var calendar = createCalendar ( )
881896 calendar. method = " REQUEST "
@@ -885,7 +900,9 @@ extension ICalendarClient {
885900 startDate: startDate,
886901 endDate: endDate,
887902 location: location,
888- description: description
903+ description: description,
904+ uid: uid,
905+ timeZone: timeZone
889906 )
890907
891908 event. organizer = organizer
@@ -908,15 +925,17 @@ extension ICalendarClient {
908925 /// Create a task list calendar
909926 public func createTaskList(
910927 title: String ,
911- tasks: [ ( summary: String , dueDate: Date ? , priority: Int ? ) ]
928+ tasks: [ ( summary: String , dueDate: Date ? , priority: Int ? ) ] ,
929+ timeZone: TimeZone = . current
912930 ) -> ICalendar {
913931 var calendar = createCalendar ( )
914932
915933 for task in tasks {
916934 let todo = createTodo (
917935 summary: task. summary,
918936 dueDate: task. dueDate,
919- priority: task. priority
937+ priority: task. priority,
938+ timeZone: timeZone
920939 )
921940 calendar. addTodo ( todo)
922941 }
@@ -989,7 +1008,7 @@ extension ICalEvent {
9891008 }
9901009
9911010 /// Check if this event is currently happening
992- public func isHappeningNow( at date: Date = Date ( ) ) -> Bool {
1011+ public func isHappeningNow( at date: Date = Date ( ) , timeZone : TimeZone = . current ) -> Bool {
9931012 guard let start = dateTimeStart? . date else { return false }
9941013
9951014 if let end = dateTimeEnd? . date {
@@ -999,22 +1018,27 @@ extension ICalEvent {
9991018 return date >= start && date <= end
10001019 } else {
10011020 // For events without end time or duration, check if it's the same day
1002- return Calendar . current. isDate ( date, inSameDayAs: start)
1021+ var calendar = Calendar . current
1022+ calendar. timeZone = timeZone
1023+ return calendar. isDate ( start, inSameDayAs: date)
10031024 }
10041025 }
10051026
10061027 /// Check if this event occurs on a specific date
1007- public func occursOn( date: Date ) -> Bool {
1028+ public func occursOn( date: Date , timeZone : TimeZone = . current ) -> Bool {
10081029 guard let start = dateTimeStart? . date else { return false }
10091030
1031+ var calendar = Calendar . current
1032+ calendar. timeZone = timeZone
1033+
10101034 if isAllDay {
1011- return Calendar . current . isDate ( start, inSameDayAs: date)
1035+ return calendar . isDate ( start, inSameDayAs: date)
10121036 } else {
10131037 if let end = dateTimeEnd? . date {
1014- return date >= Calendar . current . startOfDay ( for: start)
1015- && date <= Calendar . current . startOfDay ( for: end) . addingTimeInterval ( 86400 )
1038+ return date >= calendar . startOfDay ( for: start)
1039+ && date <= calendar . startOfDay ( for: end) . addingTimeInterval ( 86400 )
10161040 } else {
1017- return Calendar . current . isDate ( start, inSameDayAs: date)
1041+ return calendar . isDate ( start, inSameDayAs: date)
10181042 }
10191043 }
10201044 }
@@ -1110,7 +1134,8 @@ extension ICalendar {
11101134 /// Update an event by UID using a closure
11111135 public mutating func updateEvent(
11121136 withUID uid: String ,
1113- updateBlock: ( inout ICalEvent ) -> Void
1137+ updateBlock: ( inout ICalEvent ) -> Void ,
1138+ timeZone: TimeZone = . current
11141139 )
11151140 -> Bool
11161141 {
@@ -1131,7 +1156,7 @@ extension ICalendar {
11311156 // Update sequence number and last modified
11321157 let currentSequence = event. sequence ?? 0
11331158 event. sequence = currentSequence + 1
1134- event. lastModified = ICalDateTime ( date: Date ( ) )
1159+ event. lastModified = ICalDateTime ( date: Date ( ) , timeZone : timeZone )
11351160
11361161 components [ index] = event
11371162 return true
0 commit comments