|
6 | 6 | last, |
7 | 7 | modulo, |
8 | 8 | } from '../common/util.js'; |
| 9 | +import type { DateRangeValue } from '../date-range-picker/date-range-picker.js'; |
9 | 10 | import { |
10 | 11 | CalendarDay, |
11 | 12 | type CalendarRangeParams, |
@@ -71,6 +72,33 @@ export function convertToDate(value?: Date | string | null): Date | null { |
71 | 72 | return isString(value) ? parseISODate(value) : isValidDate(value); |
72 | 73 | } |
73 | 74 |
|
| 75 | +/** |
| 76 | + * Converts the given value to a DateRangeValue object. |
| 77 | + * |
| 78 | + * If the value is already a valid DateRangeValue object, it is returned directly. |
| 79 | + * If the value is a string, it is parsed to object and returned if it fields are valid dates. |
| 80 | + * If the value is null or undefined, null is returned. |
| 81 | + * If the parsing fails, null is returned. |
| 82 | + */ |
| 83 | +export function convertToDateRange( |
| 84 | + value?: DateRangeValue | string | null |
| 85 | +): DateRangeValue | null { |
| 86 | + if (!value) { |
| 87 | + return null; |
| 88 | + } |
| 89 | + |
| 90 | + if (isString(value)) { |
| 91 | + const obj = JSON.parse(value); |
| 92 | + const start = convertToDate(obj.start); |
| 93 | + const end = convertToDate(obj.end); |
| 94 | + return { |
| 95 | + start: start ? CalendarDay.from(start).native : null, |
| 96 | + end: end ? CalendarDay.from(end).native : null, |
| 97 | + }; |
| 98 | + } |
| 99 | + return value; |
| 100 | +} |
| 101 | + |
74 | 102 | /** |
75 | 103 | * Converts a Date object to an ISO 8601 string. |
76 | 104 | * |
@@ -136,26 +164,41 @@ export function isPreviousMonth(target: DayParameter, origin: DayParameter) { |
136 | 164 | } |
137 | 165 |
|
138 | 166 | /** |
139 | | - * Returns a generator yielding day values between `start` and `end` (non-inclusive) |
| 167 | + * Returns a generator yielding day values between `start` and `end` (non-inclusive by default) |
140 | 168 | * by a given `unit` as a step. |
| 169 | + * To include the end date set the `inclusive` option to true. |
141 | 170 | * |
142 | 171 | * @remarks |
143 | 172 | * By default, `unit` is set to 'day'. |
144 | 173 | */ |
145 | | -export function* calendarRange(options: CalendarRangeParams) { |
146 | | - let low = toCalendarDay(options.start); |
147 | | - const unit = options.unit ?? 'day'; |
148 | | - const high = |
149 | | - typeof options.end === 'number' |
150 | | - ? low.add(unit, options.end) |
151 | | - : toCalendarDay(options.end); |
152 | | - |
153 | | - const reverse = high.lessThan(low); |
154 | | - const step = reverse ? -1 : 1; |
155 | | - |
156 | | - while (!reverse ? low.lessThan(high) : low.greaterThan(high)) { |
157 | | - yield low; |
158 | | - low = low.add(unit, step); |
| 174 | +export function* calendarRange( |
| 175 | + options: CalendarRangeParams |
| 176 | +): Generator<CalendarDay, void, unknown> { |
| 177 | + const { start, end, unit = 'day', inclusive = false } = options; |
| 178 | + |
| 179 | + let currentDate = toCalendarDay(start); |
| 180 | + const endDate = |
| 181 | + typeof end === 'number' |
| 182 | + ? toCalendarDay(start).add(unit, end) |
| 183 | + : toCalendarDay(end); |
| 184 | + |
| 185 | + const isReversed = endDate.lessThan(currentDate); |
| 186 | + const step = isReversed ? -1 : 1; |
| 187 | + |
| 188 | + const shouldContinue = () => { |
| 189 | + if (inclusive) { |
| 190 | + return isReversed |
| 191 | + ? currentDate.greaterThanOrEqual(endDate) |
| 192 | + : currentDate.lessThanOrEqual(endDate); |
| 193 | + } |
| 194 | + return isReversed |
| 195 | + ? currentDate.greaterThan(endDate) |
| 196 | + : currentDate.lessThan(endDate); |
| 197 | + }; |
| 198 | + |
| 199 | + while (shouldContinue()) { |
| 200 | + yield currentDate; |
| 201 | + currentDate = currentDate.add(unit, step); |
159 | 202 | } |
160 | 203 | } |
161 | 204 |
|
|
0 commit comments