@zag-js/date-utils 0.70.0 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/assertion.ts DELETED
@@ -1,62 +0,0 @@
1
- import { type DateValue, isSameDay, isToday } from "@internationalized/date"
2
- import type { DateAvailableFn } from "./types"
3
-
4
- export function isTodayDate(date: DateValue, timeZone: string) {
5
- return isToday(date, timeZone)
6
- }
7
-
8
- export function isDateEqual(dateA: DateValue, dateB?: DateValue | null) {
9
- return dateB != null && isSameDay(dateA, dateB)
10
- }
11
-
12
- export function isDateInvalid(date: DateValue, minValue?: DateValue | null, maxValue?: DateValue | null) {
13
- return (minValue != null && date.compare(minValue) < 0) || (maxValue != null && date.compare(maxValue) > 0)
14
- }
15
-
16
- export function isDateDisabled(
17
- date: DateValue,
18
- startDate: DateValue,
19
- endDate: DateValue,
20
- minValue?: DateValue | null,
21
- maxValue?: DateValue | null,
22
- ) {
23
- return isDateOutsideVisibleRange(date, startDate, endDate) || isDateInvalid(date, minValue, maxValue)
24
- }
25
-
26
- export function isDateUnavailable(
27
- date: DateValue | null,
28
- isUnavailable: DateAvailableFn | undefined,
29
- locale: string,
30
- minValue?: DateValue | null,
31
- maxValue?: DateValue | null,
32
- ) {
33
- if (!date) {
34
- return false
35
- }
36
- if (isUnavailable?.(date, locale)) {
37
- return true
38
- }
39
- return isDateInvalid(date, minValue, maxValue)
40
- }
41
-
42
- export function isDateOutsideVisibleRange(date: DateValue, startDate: DateValue, endDate: DateValue) {
43
- return date.compare(startDate) < 0 || date.compare(endDate) > 0
44
- }
45
-
46
- export function isPreviousVisibleRangeInvalid(
47
- startDate: DateValue,
48
- minValue?: DateValue | null,
49
- maxValue?: DateValue | null,
50
- ) {
51
- const prevDate = startDate.subtract({ days: 1 })
52
- return isSameDay(prevDate, startDate) || isDateInvalid(prevDate, minValue, maxValue)
53
- }
54
-
55
- export function isNextVisibleRangeInvalid(
56
- endDate: DateValue,
57
- minValue?: DateValue | null,
58
- maxValue?: DateValue | null,
59
- ) {
60
- const nextDate = endDate.add({ days: 1 })
61
- return isSameDay(nextDate, endDate) || isDateInvalid(nextDate, minValue, maxValue)
62
- }
package/src/constrain.ts DELETED
@@ -1,117 +0,0 @@
1
- import {
2
- type DateDuration,
3
- type DateValue,
4
- maxDate,
5
- minDate,
6
- startOfMonth,
7
- startOfWeek,
8
- startOfYear,
9
- toCalendarDate,
10
- } from "@internationalized/date"
11
-
12
- /* -----------------------------------------------------------------------------
13
- * Align date to start, end, or center of a duration
14
- * -----------------------------------------------------------------------------*/
15
-
16
- export function alignCenter(
17
- date: DateValue,
18
- duration: DateDuration,
19
- locale: string,
20
- min?: DateValue,
21
- max?: DateValue,
22
- ): DateValue {
23
- const halfDuration: DateDuration = {}
24
-
25
- for (let prop in duration) {
26
- const key = prop as keyof DateDuration
27
-
28
- const value = duration[key]
29
- if (value == null) continue
30
-
31
- halfDuration[key] = Math.floor(value / 2)
32
-
33
- if (halfDuration[key] > 0 && value % 2 === 0) {
34
- halfDuration[key]--
35
- }
36
- }
37
-
38
- const aligned = alignStart(date, duration, locale).subtract(halfDuration)
39
-
40
- return constrainStart(date, aligned, duration, locale, min, max)
41
- }
42
-
43
- export function alignStart(
44
- date: DateValue,
45
- duration: DateDuration,
46
- locale: string,
47
- min?: DateValue,
48
- max?: DateValue,
49
- ): DateValue {
50
- // align to the start of the largest unit
51
- let aligned = date
52
- if (duration.years) {
53
- aligned = startOfYear(date)
54
- } else if (duration.months) {
55
- aligned = startOfMonth(date)
56
- } else if (duration.weeks) {
57
- aligned = startOfWeek(date, locale)
58
- }
59
-
60
- return constrainStart(date, aligned, duration, locale, min, max)
61
- }
62
-
63
- export function alignEnd(
64
- date: DateValue,
65
- duration: DateDuration,
66
- locale: string,
67
- min?: DateValue,
68
- max?: DateValue,
69
- ): DateValue {
70
- let d: DateDuration = { ...duration }
71
- // subtract 1 from the smallest unit
72
- if (d.days) {
73
- d.days--
74
- } else if (d.weeks) {
75
- d.weeks--
76
- } else if (d.months) {
77
- d.months--
78
- } else if (d.years) {
79
- d.years--
80
- }
81
-
82
- let aligned = alignStart(date, duration, locale).subtract(d)
83
- return constrainStart(date, aligned, duration, locale, min, max)
84
- }
85
-
86
- /* -----------------------------------------------------------------------------
87
- * Constrain a date to a min/max range
88
- * -----------------------------------------------------------------------------*/
89
-
90
- export function constrainStart(
91
- date: DateValue,
92
- aligned: DateValue,
93
- duration: DateDuration,
94
- locale: string,
95
- min?: DateValue,
96
- max?: DateValue,
97
- ): DateValue {
98
- if (min && date.compare(min) >= 0) {
99
- aligned = maxDate(aligned, alignStart(toCalendarDate(min), duration, locale))!
100
- }
101
-
102
- if (max && date.compare(max) <= 0) {
103
- aligned = minDate(aligned, alignEnd(toCalendarDate(max), duration, locale))!
104
- }
105
-
106
- return aligned
107
- }
108
-
109
- export function constrainValue(date: DateValue, minValue?: DateValue, maxValue?: DateValue): DateValue {
110
- if (minValue) {
111
- date = maxDate(date, toCalendarDate(minValue))!
112
- }
113
- if (maxValue) {
114
- date = minDate(date, toCalendarDate(maxValue))!
115
- }
116
- return date
117
- }
package/src/duration.ts DELETED
@@ -1,23 +0,0 @@
1
- import type { DateDuration, DateValue } from "@internationalized/date"
2
-
3
- export function getUnitDuration(duration: DateDuration) {
4
- let clone = { ...duration }
5
-
6
- for (let key in clone) {
7
- clone[key as keyof typeof clone] = 1
8
- }
9
-
10
- return clone
11
- }
12
-
13
- export function getEndDate(startDate: DateValue, duration: DateDuration) {
14
- let clone = { ...duration }
15
-
16
- if (clone.days) {
17
- clone.days--
18
- } else {
19
- clone.days = -1
20
- }
21
-
22
- return startDate.add(clone)
23
- }
@@ -1,35 +0,0 @@
1
- import type { DateValue, DateFormatter } from "@internationalized/date"
2
-
3
- export function formatRange(
4
- startDate: DateValue,
5
- endDate: DateValue,
6
- formatter: DateFormatter,
7
- toString: (start: string, end: string) => string,
8
- timeZone: string,
9
- ) {
10
- let parts = formatter.formatRangeToParts(startDate.toDate(timeZone), endDate.toDate(timeZone))
11
-
12
- let separatorIndex = -1
13
-
14
- for (let i = 0; i < parts.length; i++) {
15
- let part = parts[i]
16
- if (part.source === "shared" && part.type === "literal") {
17
- separatorIndex = i
18
- } else if (part.source === "endRange") {
19
- break
20
- }
21
- }
22
-
23
- let start = ""
24
- let end = ""
25
-
26
- for (let i = 0; i < parts.length; i++) {
27
- if (i < separatorIndex) {
28
- start += parts[i].value
29
- } else if (i > separatorIndex) {
30
- end += parts[i].value
31
- }
32
- }
33
-
34
- return toString(start, end)
35
- }
@@ -1,16 +0,0 @@
1
- import { type DateValue, isSameDay } from "@internationalized/date"
2
- import { formatRange } from "./format-range"
3
- import { getDayFormatter } from "./get-day-formatter"
4
-
5
- export function formatSelectedDate(startDate: DateValue, endDate: DateValue | null, locale: string, timeZone: string) {
6
- let start = startDate
7
- let end = endDate ?? startDate
8
-
9
- let formatter = getDayFormatter(locale, timeZone)
10
-
11
- if (isSameDay(start, end)) {
12
- return formatter.format(start.toDate(timeZone))
13
- }
14
-
15
- return formatRange(start, end, formatter, (start, end) => `${start} – ${end}`, timeZone)
16
- }
@@ -1,26 +0,0 @@
1
- import { type DateValue, endOfMonth, isSameDay, startOfMonth } from "@internationalized/date"
2
- import { getDayFormatter } from "./get-day-formatter"
3
- import { getMonthFormatter } from "./get-month-formatter"
4
-
5
- export function formatVisibleRange(startDate: DateValue, endDate: DateValue | null, locale: string, timeZone: string) {
6
- const start = startDate
7
- const end = endDate ?? startDate
8
-
9
- const dayFormatter = getDayFormatter(locale, timeZone)
10
-
11
- if (!isSameDay(start, startOfMonth(start))) {
12
- return dayFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone))
13
- }
14
-
15
- const monthFormatter = getMonthFormatter(locale, timeZone)
16
-
17
- if (isSameDay(end, endOfMonth(start))) {
18
- return monthFormatter.format(start.toDate(timeZone))
19
- }
20
-
21
- if (isSameDay(end, endOfMonth(end))) {
22
- return monthFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone))
23
- }
24
-
25
- return ""
26
- }
@@ -1,14 +0,0 @@
1
- import { DateFormatter, toCalendarDateTime, today } from "@internationalized/date"
2
- import { getEraFormat } from "./get-era-format"
3
-
4
- export function getDayFormatter(locale: string, timeZone: string) {
5
- const date = toCalendarDateTime(today(timeZone))
6
- return new DateFormatter(locale, {
7
- weekday: "long",
8
- month: "long",
9
- year: "numeric",
10
- day: "numeric",
11
- era: getEraFormat(date),
12
- timeZone,
13
- })
14
- }
@@ -1,12 +0,0 @@
1
- export function getDecadeRange(year: number) {
2
- const computedYear = year - (year % 10) - 1
3
-
4
- const years: number[] = []
5
-
6
- for (let i = 0; i < 12; i += 1) {
7
- const value = computedYear + i
8
- years.push(value)
9
- }
10
-
11
- return years
12
- }
@@ -1,6 +0,0 @@
1
- import type { DateValue } from "@internationalized/date"
2
- import { getStartOfWeek } from "./get-start-of-week"
3
-
4
- export function getEndOfWeek(date: DateValue, locale: string, firstDayOfWeek: number = 0) {
5
- return getStartOfWeek(date, locale, firstDayOfWeek).add({ days: 6 })
6
- }
@@ -1,5 +0,0 @@
1
- import type { DateValue } from "@internationalized/date"
2
-
3
- export function getEraFormat(date: DateValue | undefined): "short" | undefined {
4
- return date?.calendar.identifier === "gregory" && date.era === "BC" ? "short" : undefined
5
- }
@@ -1,33 +0,0 @@
1
- import { type DateValue, getWeeksInMonth, isSameDay, getDayOfWeek, startOfMonth } from "@internationalized/date"
2
- import { getStartOfWeek } from "./get-start-of-week"
3
-
4
- export function getDaysInWeek(weekIndex: number, from: DateValue, locale: string, firstDayOfWeek?: number) {
5
- const weekDate = from.add({ weeks: weekIndex })
6
- const dates: DateValue[] = []
7
- let date = getStartOfWeek(weekDate, locale, firstDayOfWeek)
8
- while (dates.length < 7) {
9
- dates.push(date)
10
- let nextDate = date.add({ days: 1 })
11
- if (isSameDay(date, nextDate)) {
12
- break
13
- }
14
- date = nextDate
15
- }
16
- return dates
17
- }
18
-
19
- export function getCustomWeeksInMonth(from: DateValue, locale: string, firstDayOfWeek?: number) {
20
- if (firstDayOfWeek == null) {
21
- return getWeeksInMonth(from, locale)
22
- }
23
- const paddingDays = (getDayOfWeek(startOfMonth(from), locale) - firstDayOfWeek + 7) % 7
24
-
25
- return Math.ceil((paddingDays + from.calendar.getDaysInMonth(from)) / 7)
26
- }
27
-
28
- export function getMonthDays(from: DateValue, locale: string, numOfWeeks?: number, firstDayOfWeek?: number) {
29
- const monthWeeks = numOfWeeks ?? getCustomWeeksInMonth(from, locale, firstDayOfWeek)
30
-
31
- const weeks = [...new Array(monthWeeks).keys()]
32
- return weeks.map((week) => getDaysInWeek(week, from, locale, firstDayOfWeek))
33
- }
@@ -1,13 +0,0 @@
1
- import { today, toCalendarDate, DateFormatter } from "@internationalized/date"
2
- import { getEraFormat } from "./get-era-format"
3
-
4
- export function getMonthFormatter(locale: string, timeZone: string) {
5
- const date = toCalendarDate(today(timeZone))
6
- return new DateFormatter(locale, {
7
- month: "long",
8
- year: "numeric",
9
- era: getEraFormat(date),
10
- calendar: date?.calendar.identifier,
11
- timeZone: timeZone,
12
- })
13
- }
@@ -1,9 +0,0 @@
1
- export function getMonthNames(locale: string, format: Intl.DateTimeFormatOptions["month"] = "long") {
2
- const date = new Date(2021, 0, 1)
3
- const monthNames: string[] = []
4
- for (let i = 0; i < 12; i++) {
5
- monthNames.push(date.toLocaleString(locale, { month: format }))
6
- date.setMonth(date.getMonth() + 1)
7
- }
8
- return monthNames
9
- }
@@ -1,14 +0,0 @@
1
- import { type DateValue, getDayOfWeek, startOfWeek } from "@internationalized/date"
2
-
3
- export function getStartOfWeek(date: DateValue, locale: string, firstDayOfWeek?: number) {
4
- // If firstDayOfWeek is provided, use it; otherwise, use the locale's default
5
- if (firstDayOfWeek !== undefined) {
6
- // Adjust the date to the specified first day of the week
7
- const currentDayOfWeek = getDayOfWeek(date, locale)
8
- const daysToSubtract = (currentDayOfWeek - firstDayOfWeek + 7) % 7
9
- return date.subtract({ days: daysToSubtract })
10
- }
11
-
12
- // Use the built-in startOfWeek function for locale-specific behavior
13
- return startOfWeek(date, locale)
14
- }
@@ -1,10 +0,0 @@
1
- import type { DateValue } from "@internationalized/date"
2
- import { getWeekdayFormats } from "./get-weekday-formats"
3
- import { getStartOfWeek } from "./get-start-of-week"
4
-
5
- export function getWeekDays(date: DateValue, startOfWeekProp: number | undefined, timeZone: string, locale: string) {
6
- const firstDayOfWeek = getStartOfWeek(date, locale, startOfWeekProp)
7
- const weeks = [...new Array(7).keys()]
8
- const format = getWeekdayFormats(locale, timeZone)
9
- return weeks.map((index) => format(firstDayOfWeek.add({ days: index })))
10
- }
@@ -1,16 +0,0 @@
1
- import { type DateValue, DateFormatter } from "@internationalized/date"
2
-
3
- export function getWeekdayFormats(locale: string, timeZone: string) {
4
- const longFormat = new DateFormatter(locale, { weekday: "long", timeZone })
5
- const shortFormat = new DateFormatter(locale, { weekday: "short", timeZone })
6
- const narrowFormat = new DateFormatter(locale, { weekday: "narrow", timeZone })
7
- return <T extends DateValue | Date>(value: T) => {
8
- const date = value instanceof Date ? value : value.toDate(timeZone)
9
- return {
10
- value,
11
- short: shortFormat.format(date),
12
- long: longFormat.format(date),
13
- narrow: narrowFormat.format(date),
14
- }
15
- }
16
- }
@@ -1,14 +0,0 @@
1
- export interface YearsRange {
2
- from: number
3
- to: number
4
- }
5
-
6
- export function getYearsRange(range: YearsRange) {
7
- const years: number[] = []
8
-
9
- for (let year = range.from; year <= range.to; year += 1) {
10
- years.push(year)
11
- }
12
-
13
- return years
14
- }
package/src/index.ts DELETED
@@ -1,20 +0,0 @@
1
- export * from "./align"
2
- export * from "./assertion"
3
- export * from "./constrain"
4
- export * from "./duration"
5
- export * from "./format-range"
6
- export * from "./format-selected-date"
7
- export * from "./format-visible-range"
8
- export * from "./get-day-formatter"
9
- export * from "./get-decade-range"
10
- export * from "./get-month-days"
11
- export * from "./get-month-formatter"
12
- export * from "./get-month-names"
13
- export * from "./get-week-days"
14
- export * from "./get-weekday-formats"
15
- export * from "./get-year-range"
16
- export * from "./mutation"
17
- export * from "./pagination"
18
- export * from "./parse-date"
19
- export * from "./preset"
20
- export type { DateAdjustFn, DateGranularity } from "./types"
package/src/mutation.ts DELETED
@@ -1,67 +0,0 @@
1
- import {
2
- type Calendar,
3
- type DateValue,
4
- getLocalTimeZone,
5
- toCalendar,
6
- toCalendarDateTime,
7
- today,
8
- } from "@internationalized/date"
9
- import { constrainValue } from "./constrain"
10
- import type { DateAvailableFn } from "./types"
11
-
12
- export function getTodayDate(timeZone?: string) {
13
- return today(timeZone ?? getLocalTimeZone())
14
- }
15
-
16
- export function getNextDay(date: DateValue) {
17
- return date.add({ days: 1 })
18
- }
19
-
20
- export function getPreviousDay(date: DateValue) {
21
- return date.subtract({ days: 1 })
22
- }
23
-
24
- export function setMonth(date: DateValue, month: number) {
25
- return date.set({ month })
26
- }
27
-
28
- export function setYear(date: DateValue, year: number) {
29
- return date.set({ year })
30
- }
31
-
32
- export function setCalendar(date: DateValue, calendar: Calendar) {
33
- return toCalendar(toCalendarDateTime(date), calendar)
34
- }
35
-
36
- export function setDate(
37
- date: DateValue,
38
- startDate: DateValue,
39
- isDateUnavailable: DateAvailableFn,
40
- locale: string,
41
- minValue: DateValue,
42
- maxValue: DateValue,
43
- ) {
44
- let result: DateValue | undefined
45
- result = constrainValue(date, minValue, maxValue)
46
- result = getPreviousAvailableDate(date, startDate, locale, isDateUnavailable)
47
- return result
48
- }
49
-
50
- export function getPreviousAvailableDate(
51
- date: DateValue,
52
- minValue: DateValue,
53
- locale: string,
54
- isDateUnavailable?: DateAvailableFn,
55
- ) {
56
- if (!isDateUnavailable) {
57
- return date
58
- }
59
-
60
- while (date.compare(minValue) >= 0 && isDateUnavailable(date, locale)) {
61
- date = date.subtract({ days: 1 })
62
- }
63
-
64
- if (date.compare(minValue) >= 0) {
65
- return date
66
- }
67
- }
@@ -1,20 +0,0 @@
1
- const FUTURE_YEAR_COERCION = 10
2
-
3
- export function normalizeYear(year: string | null | undefined) {
4
- if (!year) return
5
-
6
- if (year.length === 3) {
7
- return year.padEnd(4, "0")
8
- }
9
-
10
- if (year.length === 2) {
11
- const currentYear = new Date().getFullYear()
12
- const currentCentury = Math.floor(currentYear / 100) * 100
13
- const twoDigitYear = parseInt(year.slice(-2), 10)
14
-
15
- const fullYear = currentCentury + twoDigitYear
16
- return fullYear > currentYear + FUTURE_YEAR_COERCION ? (fullYear - 100).toString() : fullYear.toString()
17
- }
18
-
19
- return year
20
- }