11import '../../document/document.dart' ;
22import '../semantic.dart' ;
33
4+ /// Helper function to determine if a component spans multiple days.
5+ ///
6+ /// [duration] is the effective duration of the component.
7+ /// [startDate] is the start date/time of the component.
8+ /// [endDate] is the end date/time of the component.
9+ ///
10+ /// Returns true if the component appears on more than one calendar day.
11+ bool _isMultiDay ({
12+ required CalDuration ? duration,
13+ required CalDateTime ? startDate,
14+ required CalDateTime ? endDate,
15+ }) {
16+ if (duration == null ) return false ;
17+
18+ // For negative durations, consider it not multi-day
19+ if (duration.sign == Sign .negative) return false ;
20+
21+ // For all-day items (DATE values), check if duration is MORE than 1 day
22+ final isAllDay = startDate? .isDate ?? false ;
23+ if (isAllDay) {
24+ return duration.days > 1 ;
25+ }
26+
27+ // For timed items, check if duration is at least 1 day
28+ // or if it crosses midnight
29+ if (duration.days > 0 ) return true ;
30+
31+ // For items with only hours/minutes/seconds, check if it crosses midnight
32+ if (endDate != null && startDate != null ) {
33+ return startDate.day != endDate.day ||
34+ startDate.month != endDate.month ||
35+ startDate.year != endDate.year;
36+ }
37+
38+ return false ;
39+ }
40+
441/// Extensions for [EventComponent] to enhance functionality.
542extension EventComponentExtensions on EventComponent {
643 /// Determines if the event is recurring based on the presence of
@@ -10,6 +47,18 @@ extension EventComponentExtensions on EventComponent {
1047 /// Returns true if this event is an all-day event
1148 bool get isAllDay => dtstart? .isDate ?? false ;
1249
50+ /// Returns true if this event spans multiple days.
51+ ///
52+ /// An event is considered multi-day if it appears on more than one calendar day.
53+ /// For all-day events, this means the duration is more than 1 day.
54+ /// For timed events, this means it crosses midnight to a different day.
55+ /// Returns false if the event has no end time or duration.
56+ bool get isMultiDay => _isMultiDay (
57+ duration: effectiveDuration,
58+ startDate: dtstart,
59+ endDate: effectiveEnd,
60+ );
61+
1362 /// Returns the effective end time (dtend or dtstart + duration)
1463 CalDateTime ? get effectiveEnd {
1564 if (dtend != null ) return dtend;
@@ -68,6 +117,17 @@ extension TodoComponentExtensions on TodoComponent {
68117 /// a recurrence rule (RRULE) or recurrence dates (RDATE).
69118 bool get isRecurring => rrule != null || rdates.isNotEmpty;
70119
120+ /// Returns true if this todo spans multiple days.
121+ ///
122+ /// A todo is considered multi-day if it appears on more than one calendar day.
123+ /// This is determined by the duration from [dtstart] to [due] .
124+ /// Returns false if the todo has no due date or duration.
125+ bool get isMultiDay => _isMultiDay (
126+ duration: effectiveDuration,
127+ startDate: dtstart,
128+ endDate: due,
129+ );
130+
71131 /// Returns the effective duration of the todo.
72132 ///
73133 /// If [duration] is specified, returns it directly.
0 commit comments