Skip to content

Commit 61feed3

Browse files
committed
Reduce diff
Signed-off-by: gpbl <io@gpbl.dev>
1 parent dcf496e commit 61feed3

File tree

7 files changed

+56
-73
lines changed

7 files changed

+56
-73
lines changed

examples/TimeZoneNoonSafeSimple.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ export function TimeZoneNoonSafeSimple() {
77
const [selected, setSelected] = useState<Date | undefined>(
88
new TZDate(1900, 11, 1, timeZone),
99
);
10+
const formatter = new Intl.DateTimeFormat("en-US", {
11+
dateStyle: "full",
12+
timeStyle: "short",
13+
timeZone,
14+
});
1015

1116
return (
1217
<DayPicker
@@ -20,8 +25,8 @@ export function TimeZoneNoonSafeSimple() {
2025
onSelect={setSelected}
2126
footer={
2227
selected
23-
? `Selected: ${selected.toString()}`
24-
: "Pick a day to see the time zone-aware date"
28+
? `Selected: ${formatter.format(selected)} (${timeZone})`
29+
: `Pick a day to see it in ${timeZone}`
2530
}
2631
/>
2732
);

src/DayPicker.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { getMonthOptions } from "./helpers/getMonthOptions.js";
1313
import { getStyleForModifiers } from "./helpers/getStyleForModifiers.js";
1414
import { getWeekdays } from "./helpers/getWeekdays.js";
1515
import { getYearOptions } from "./helpers/getYearOptions.js";
16-
import { createNoonDateLibOverrides } from "./noonDateLib.js";
16+
import { createNoonOverrides } from "./noonDateLib.js";
1717
import type {
1818
DayPickerProps,
1919
Modifiers,
@@ -105,7 +105,7 @@ export function DayPicker(initialProps: DayPickerProps) {
105105

106106
const noonOverrides =
107107
props.noonSafe && props.timeZone
108-
? createNoonDateLibOverrides({
108+
? createNoonOverrides({
109109
timeZone: props.timeZone,
110110
weekStartsOn,
111111
locale,
@@ -114,7 +114,7 @@ export function DayPicker(initialProps: DayPickerProps) {
114114
const overrides =
115115
props.dateLib && noonOverrides
116116
? { ...noonOverrides, ...props.dateLib }
117-
: props.dateLib ?? noonOverrides;
117+
: (props.dateLib ?? noonOverrides);
118118

119119
const dateLib = new DateLib(
120120
{

src/helpers/getDates.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,5 @@ export function getDates(
8383
dates.push(date);
8484
}
8585
}
86-
87-
if (hasDuplicateDay(dates, dateLib)) {
88-
// Useful for diagnosing timezone/date-lib edge cases without changing behavior.
89-
console.warn("DayPicker: duplicate calendar days detected in getDates", {
90-
dates,
91-
});
92-
}
93-
9486
return dates;
9587
}
96-
97-
/**
98-
* Returns `true` when the list contains at least two dates falling on the same
99-
* calendar day (after normalizing to the start of the day with `dateLib`).
100-
*/
101-
export function hasDuplicateDay(dates: Date[], dateLib: DateLib): boolean {
102-
const seen = new Set<string>();
103-
for (const day of dates) {
104-
// Key by the calendar components of the original date to avoid timezone
105-
// and sub-hour offsets shifting us into the previous/next day.
106-
const key = `${dateLib.getYear(day)}-${dateLib.getMonth(day)}-${day.getDate()}`;
107-
if (seen.has(key)) {
108-
return true;
109-
}
110-
seen.add(key);
111-
}
112-
return false;
113-
}

src/noonDateLib.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from "date-fns";
1313
import type { DateLib } from "./classes/DateLib.js";
1414

15-
export interface CreateNoonDateLibOverridesOptions {
15+
export interface CreateNoonOverridesOptions {
1616
timeZone?: string;
1717
weekStartsOn?: number;
1818
locale?: Locale;
@@ -23,12 +23,14 @@ export interface CreateNoonDateLibOverridesOptions {
2323
* time zone. This avoids second-level offset changes (e.g., historical zones
2424
* with +03:41:12) from pushing dates backward across midnight.
2525
*/
26-
export function createNoonDateLibOverrides(
27-
options: CreateNoonDateLibOverridesOptions = {},
26+
export function createNoonOverrides(
27+
options: CreateNoonOverridesOptions = {},
2828
): Partial<typeof DateLib.prototype> {
2929
const { timeZone, weekStartsOn, locale } = options;
30-
const fallbackWeekStartsOn =
31-
weekStartsOn ?? locale?.options?.weekStartsOn ?? 0;
30+
type WeekStartsOn = NonNullable<StartOfWeekOptions["weekStartsOn"]>;
31+
const fallbackWeekStartsOn: WeekStartsOn = (weekStartsOn ??
32+
locale?.options?.weekStartsOn ??
33+
0) as WeekStartsOn;
3234

3335
const normalize = (date: Date | number | string) => {
3436
const normalizedDate =
@@ -70,7 +72,8 @@ export function createNoonDateLibOverrides(
7072
},
7173
startOfWeek: (date, options?: StartOfWeekOptions) => {
7274
const base = normalize(date);
73-
const weekStartsOnValue = options?.weekStartsOn ?? fallbackWeekStartsOn;
75+
const weekStartsOnValue =
76+
(options?.weekStartsOn ?? fallbackWeekStartsOn) as WeekStartsOn;
7477
const diff = (base.getDay() - weekStartsOnValue + 7) % 7;
7578
return normalize(
7679
new TZDate(
@@ -108,7 +111,8 @@ export function createNoonDateLibOverrides(
108111

109112
endOfWeek: (date, options?: EndOfWeekOptions) => {
110113
const base = normalize(date);
111-
const weekStartsOnValue = options?.weekStartsOn ?? fallbackWeekStartsOn;
114+
const weekStartsOnValue =
115+
(options?.weekStartsOn ?? fallbackWeekStartsOn) as WeekStartsOn;
112116
const endDow = (weekStartsOnValue + 6) % 7;
113117
const diff = (endDow - base.getDay() + 7) % 7;
114118
return normalize(

src/noonJalaliDateLib.ts

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,22 @@ import {
2020
} from "date-fns-jalali";
2121

2222
import type { DateLib } from "./classes/DateLib.js";
23-
import type { CreateNoonDateLibOverridesOptions } from "./noonDateLib.js";
23+
import type { CreateNoonOverridesOptions } from "./noonDateLib.js";
2424

2525
/**
2626
* Jalali-aware version of {@link createNoonDateLibOverrides}.
2727
*
2828
* Keeps all calendar math at noon in the target time zone while deferring to
2929
* `date-fns-jalali` for calendar logic.
3030
*/
31-
export function createJalaliNoonDateLibOverrides(
32-
options: CreateNoonDateLibOverridesOptions = {},
31+
export function createJalaliNoonOverrides(
32+
options: CreateNoonOverridesOptions = {},
3333
): Partial<typeof DateLib.prototype> {
3434
const { timeZone, weekStartsOn, locale } = options;
35-
const fallbackWeekStartsOn =
36-
weekStartsOn ?? locale?.options?.weekStartsOn ?? 0;
35+
type WeekStartsOn = NonNullable<StartOfWeekOptions["weekStartsOn"]>;
36+
const fallbackWeekStartsOn: WeekStartsOn = (weekStartsOn ??
37+
locale?.options?.weekStartsOn ??
38+
0) as WeekStartsOn;
3739

3840
const normalize = (date: Date | number | string) => {
3941
const normalizedDate =
@@ -67,7 +69,8 @@ export function createJalaliNoonDateLibOverrides(
6769
},
6870
startOfWeek: (date, options?: StartOfWeekOptions) => {
6971
const base = normalize(date);
70-
const weekStartsOnValue = options?.weekStartsOn ?? fallbackWeekStartsOn;
72+
const weekStartsOnValue =
73+
(options?.weekStartsOn ?? fallbackWeekStartsOn) as WeekStartsOn;
7174
return normalize(
7275
startOfWeekJalali(base, {
7376
weekStartsOn: weekStartsOnValue,
@@ -78,14 +81,13 @@ export function createJalaliNoonDateLibOverrides(
7881
const base = normalize(date);
7982
return normalize(startOfISOWeekJalali(base));
8083
},
81-
startOfMonth: (date) =>
82-
normalize(startOfMonthJalali(normalize(date))),
83-
startOfYear: (date) =>
84-
normalize(startOfYearJalali(normalize(date))),
84+
startOfMonth: (date) => normalize(startOfMonthJalali(normalize(date))),
85+
startOfYear: (date) => normalize(startOfYearJalali(normalize(date))),
8586

8687
endOfWeek: (date, options?: EndOfWeekOptions) => {
8788
const base = normalize(date);
88-
const weekStartsOnValue = options?.weekStartsOn ?? fallbackWeekStartsOn;
89+
const weekStartsOnValue =
90+
(options?.weekStartsOn ?? fallbackWeekStartsOn) as WeekStartsOn;
8991
return normalize(
9092
endOfWeekJalali(base, {
9193
weekStartsOn: weekStartsOnValue,
@@ -96,19 +98,14 @@ export function createJalaliNoonDateLibOverrides(
9698
const base = normalize(date);
9799
return normalize(endOfISOWeekJalali(base));
98100
},
99-
endOfMonth: (date) =>
100-
normalize(endOfMonthJalali(normalize(date))),
101-
endOfYear: (date) =>
102-
normalize(endOfYearJalali(normalize(date))),
101+
endOfMonth: (date) => normalize(endOfMonthJalali(normalize(date))),
102+
endOfYear: (date) => normalize(endOfYearJalali(normalize(date))),
103103

104104
eachMonthOfInterval: (interval) => {
105-
return eachMonthOfIntervalJalali(
106-
{
107-
start: normalize(interval.start),
108-
end: normalize(interval.end),
109-
},
110-
{ weekStartsOn: fallbackWeekStartsOn },
111-
).map((date) => normalize(date));
105+
return eachMonthOfIntervalJalali({
106+
start: normalize(interval.start),
107+
end: normalize(interval.end),
108+
}).map((date) => normalize(date));
112109
},
113110

114111
addDays: (date, amount) =>

src/persian.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from "./index.js";
99
import { enUSJalali } from "./locale/en-US-jalali.js";
1010
import { faIRJalali } from "./locale/fa-IR-jalali.js";
11-
import { createJalaliNoonDateLibOverrides } from "./noonJalaliDateLib.js";
11+
import { createJalaliNoonOverrides } from "./noonJalaliDateLib.js";
1212
import type { DayPickerProps } from "./types/props.js";
1313

1414
/** Persian (Iran) Jalali locale with DayPicker labels. */
@@ -115,16 +115,17 @@ export const getDateLib = (
115115
},
116116
) => {
117117
const { noonSafe, overrides, ...dateLibOptions } = options ?? {};
118-
const baseOverrides = noonSafe && dateLibOptions.timeZone
119-
? {
120-
...dateFnsJalali,
121-
...createJalaliNoonDateLibOverrides({
122-
timeZone: dateLibOptions.timeZone,
123-
weekStartsOn: dateLibOptions.weekStartsOn,
124-
locale: dateLibOptions.locale,
125-
}),
126-
}
127-
: dateFnsJalali;
118+
const baseOverrides =
119+
noonSafe && dateLibOptions.timeZone
120+
? {
121+
...dateFnsJalali,
122+
...createJalaliNoonOverrides({
123+
timeZone: dateLibOptions.timeZone,
124+
weekStartsOn: dateLibOptions.weekStartsOn,
125+
locale: dateLibOptions.locale,
126+
}),
127+
}
128+
: dateFnsJalali;
128129

129130
return new DateLib(dateLibOptions, { ...baseOverrides, ...overrides });
130131
};

website/docs/localization/setting-time-zone.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The time zone can be specified as either an [IANA time zone](https://en.wikipedi
1212
| Prop Name | Type | Description |
1313
| ---------- | --------- | ------------------------------------------------------------------------------------ |
1414
| `timeZone` | `string` | The IANA time zone to use when rendering the calendar. |
15-
| `noonSafe` | `boolean` | Experimental. Keep calendar math at noon in the time zone to avoid historical drift. |
15+
| `noonSafe` | `boolean` | Experimental (see below). Keep calendar math at noon in the time zone to avoid historical drift and use when your time zone shows duplicated/missing days. |
1616

1717
```tsx
1818
<DayPicker timeZone="UTC" /> // Coordinated Universal Time
@@ -69,7 +69,9 @@ const timeZone = "Asia/Dubai";
6969
```
7070

7171
This override is optional and only needed when you render months that include
72-
offsets with seconds and want to avoid duplicate or missing days in the grid.
72+
offsets with seconds and want to avoid duplicate or missing days in the grid. Use
73+
it when you notice time-zone related glitches such as missing days, duplicate
74+
days, or unexpected week padding.
7375

7476
<BrowserWindow bodyStyle={{ justifyContent: "start" }}>
7577
<Examples.TimeZoneNoonSafeSimple />

0 commit comments

Comments
 (0)