Skip to content

Commit c194e02

Browse files
authored
Adjust min/max value with timezone offset in date-picker-cell (#1042)
1 parent bbb6809 commit c194e02

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

packages/cells/src/cells/date-picker-cell.tsx

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export interface DatePickerCellProps {
3131
readonly displayDate: string;
3232
/* Defines the type of the HTML input element. */
3333
readonly format: DateKind;
34-
/* Timezone offset in minutes.
34+
/* Timezone offset in minutes.
3535
This can be used to adjust the date by a given timezone offset. */
3636
readonly timezoneOffset?: number;
3737
/* Minimum value that can be entered by the user.
@@ -40,17 +40,27 @@ export interface DatePickerCellProps {
4040
/* Maximum value that can be entered by the user.
4141
This is passed to the max attribute of the HTML input element. */
4242
readonly max?: string | Date;
43-
/* Granularity that the date must adhere.
43+
/* Granularity that the date must adhere.
4444
This is passed to the step attribute of the HTML input element. */
4545
readonly step?: string;
4646
}
4747

4848
export type DateKind = "date" | "time" | "datetime-local";
4949

50-
export const formatValueForHTMLInput = (dateKind: DateKind, date: Date | undefined | null): string => {
50+
export const formatValueForHTMLInput = (
51+
dateKind: DateKind,
52+
date: Date | undefined | null,
53+
timezoneOffsetMs?: number
54+
): string => {
5155
if (date === undefined || date === null) {
5256
return "";
5357
}
58+
59+
if (timezoneOffsetMs) {
60+
// Adjust based on the configured timezone offset:
61+
date = new Date(date.getTime() + timezoneOffsetMs);
62+
}
63+
5464
const isoDate = date.toISOString();
5565
switch (dateKind) {
5666
case "date":
@@ -72,18 +82,18 @@ const Editor: ReturnType<ProvideEditorCallback<DatePickerCell>> = cell => {
7282
const step =
7383
cellData.step !== undefined && !Number.isNaN(Number(cellData.step)) ? Number(cellData.step) : undefined;
7484

75-
const minValue = cellData.min instanceof Date ? formatValueForHTMLInput(format, cellData.min) : cellData.min;
85+
// Convert timezone offset from minutes to milliseconds:
86+
const timezoneOffsetMs = cellData.timezoneOffset ? cellData.timezoneOffset * 60 * 1000 : 0;
7687

77-
const maxValue = cellData.max instanceof Date ? formatValueForHTMLInput(format, cellData.max) : cellData.max;
88+
// We need to convert the min and max to iso strings. Thereby, we are also
89+
// adjusting the values to the given timezone offset.
90+
const minValue =
91+
cellData.min instanceof Date ? formatValueForHTMLInput(format, cellData.min, timezoneOffsetMs) : cellData.min;
92+
const maxValue =
93+
cellData.max instanceof Date ? formatValueForHTMLInput(format, cellData.max, timezoneOffsetMs) : cellData.max;
94+
95+
const value = formatValueForHTMLInput(format, cellData.date, timezoneOffsetMs);
7896

79-
let date = cellData.date;
80-
// Convert timezone offset to milliseconds
81-
const timezoneOffsetMs = cellData.timezoneOffset ? cellData.timezoneOffset * 60 * 1000 : 0;
82-
if (timezoneOffsetMs && date) {
83-
// Adjust based on the timezone offset
84-
date = new Date(date.getTime() + timezoneOffsetMs);
85-
}
86-
const value = formatValueForHTMLInput(format, date);
8797
if (cell.value.readonly) {
8898
return (
8999
<TextCellEntry

packages/cells/test/date-picker-cell.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ describe("formatValueForHTMLInput", () => {
1717
])("check %p format and %p date leads correct format: {%p}", (format: string, date: Date, valueForHTML: string) => {
1818
expect(formatValueForHTMLInput(format as DateKind, date)).toStrictEqual(valueForHTML);
1919
});
20+
21+
it.each([
22+
["datetime-local", new Date("2023-01-01T12:00:00.000Z"), 60 * 60 * 1000, "2023-01-01T13:00:00.000"],
23+
["datetime-local", new Date("2023-01-01T12:00:00.000Z"), -60 * 60 * 1000, "2023-01-01T11:00:00.000"],
24+
["date", new Date("2023-01-01T23:30:00.000Z"), 60 * 60 * 1000, "2023-01-02"],
25+
["date", new Date("2023-01-02T00:30:00.000Z"), -60 * 60 * 1000, "2023-01-01"],
26+
["time", new Date("1970-01-01T10:00:00.000Z"), 30 * 60 * 1000, "10:30:00.000"],
27+
["time", new Date("1970-01-01T10:00:00.000Z"), -30 * 60 * 1000, "09:30:00.000"],
28+
])(
29+
"check %p format and %p date with timezoneOffsetMs %p leads to correct format: %p",
30+
(format: string, date: Date, timezoneOffsetMs: number, valueForHTML: string) => {
31+
expect(formatValueForHTMLInput(format as DateKind, date, timezoneOffsetMs)).toStrictEqual(valueForHTML);
32+
}
33+
);
34+
2035
it("throws an error when a weird value is passed", () => {
2136
expect(() => formatValueForHTMLInput("weird" as DateKind, new Date())).toThrow("Unknown date kind weird");
2237
});

0 commit comments

Comments
 (0)