From 0fb9933cbe1854db85adde18d76b644b9c280ba9 Mon Sep 17 00:00:00 2001 From: Jonah Scheinerman Date: Wed, 11 Dec 2024 10:53:15 -0500 Subject: [PATCH 1/3] fix(DateInput3): Fix wrong Today date for timezone mismatch --- .../src/components/date-input3/dateInput3.tsx | 1 + .../src/components/date-picker3/datePicker3.tsx | 11 +++++++---- .../src/components/date-picker3/datePicker3Props.ts | 10 ++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/datetime2/src/components/date-input3/dateInput3.tsx b/packages/datetime2/src/components/date-input3/dateInput3.tsx index f8d1cde790..3d9cfafdc0 100644 --- a/packages/datetime2/src/components/date-input3/dateInput3.tsx +++ b/packages/datetime2/src/components/date-input3/dateInput3.tsx @@ -290,6 +290,7 @@ export const DateInput3: React.FC = React.memo(function _DateIn onShortcutChange={handleShortcutChange} selectedShortcutIndex={selectedShortcutIndex} timePrecision={timePrecision} + timezone={timezoneValue} // the rest of this component handles invalid dates gracefully (to show error messages), // but DatePicker does not, so we must take care to filter those out value={isErrorState ? null : valueAsDate} diff --git a/packages/datetime2/src/components/date-picker3/datePicker3.tsx b/packages/datetime2/src/components/date-picker3/datePicker3.tsx index 7ca7e8c2d1..086936ff22 100644 --- a/packages/datetime2/src/components/date-picker3/datePicker3.tsx +++ b/packages/datetime2/src/components/date-picker3/datePicker3.tsx @@ -28,6 +28,7 @@ import { DateUtils, Errors, TimePicker, + TimezoneUtils, } from "@blueprintjs/datetime"; import { Classes, dayPickerClassNameOverrides } from "../../classes"; @@ -240,9 +241,9 @@ export class DatePicker3 extends DateFnsLocalizedComponent ({ - ...shortcut, - dateRange: [shortcut.date, null], - })); + ...shortcut, + dateRange: [shortcut.date, null], + })); return [ { - const value = new Date(); + const { timezone } = this.props; + const today = new Date(); + const value = timezone != null ? TimezoneUtils.convertLocalDateToTimezoneTime(today, timezone) : today; const displayMonth = value.getMonth(); const displayYear = value.getFullYear(); const selectedDay = value.getDate(); diff --git a/packages/datetime2/src/components/date-picker3/datePicker3Props.ts b/packages/datetime2/src/components/date-picker3/datePicker3Props.ts index 550b391d49..51b747834f 100644 --- a/packages/datetime2/src/components/date-picker3/datePicker3Props.ts +++ b/packages/datetime2/src/components/date-picker3/datePicker3Props.ts @@ -45,4 +45,14 @@ export interface DatePicker3Props extends DatePickerSharedProps, DateFnsLocalePr * The currently selected day. If this prop is provided, the component acts in a controlled manner. */ value?: Date | null; + + /** + * The currently selected timezone UTC identifier, e.g. "Pacific/Honolulu". + * + * This prop is only used to determine what date should be selected when clicking the "Today" button in the actions + * bar. If this value is omitted, the current date will be set using the user's local timezone. + * + * See [IANA Time Zones](https://www.iana.org/time-zones). + */ + timezone?: string; } From 4ff1c48fbd8c97e67ec98ceae4ca38a6987fb4ff Mon Sep 17 00:00:00 2001 From: Jonah Scheinerman Date: Wed, 11 Dec 2024 11:02:52 -0500 Subject: [PATCH 2/3] Prettier fix --- .../datetime2/src/components/date-picker3/datePicker3.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/datetime2/src/components/date-picker3/datePicker3.tsx b/packages/datetime2/src/components/date-picker3/datePicker3.tsx index 086936ff22..4ec8ae4c58 100644 --- a/packages/datetime2/src/components/date-picker3/datePicker3.tsx +++ b/packages/datetime2/src/components/date-picker3/datePicker3.tsx @@ -241,9 +241,9 @@ export class DatePicker3 extends DateFnsLocalizedComponent ({ - ...shortcut, - dateRange: [shortcut.date, null], - })); + ...shortcut, + dateRange: [shortcut.date, null], + })); return [ Date: Wed, 11 Dec 2024 12:31:35 -0500 Subject: [PATCH 3/3] Tests --- packages/datetime2/karma.conf.js | 1 + .../test/components/datePicker3Tests.tsx | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/datetime2/karma.conf.js b/packages/datetime2/karma.conf.js index cd949b02cd..46e1233087 100644 --- a/packages/datetime2/karma.conf.js +++ b/packages/datetime2/karma.conf.js @@ -33,4 +33,5 @@ module.exports = async function (config) { }, }), ); + process.env.TZ = 'Etc/UTC'; }; diff --git a/packages/datetime2/test/components/datePicker3Tests.tsx b/packages/datetime2/test/components/datePicker3Tests.tsx index 4e060ac28c..29874abcb3 100644 --- a/packages/datetime2/test/components/datePicker3Tests.tsx +++ b/packages/datetime2/test/components/datePicker3Tests.tsx @@ -801,6 +801,16 @@ describe("", () => { }); describe("clearing a selection", () => { + const MOCK_TODAY = new Date(2024, 11, 24, 16, 30); + let clock: sinon.SinonFakeTimers; + beforeEach(() => { + clock = sinon.useFakeTimers(MOCK_TODAY); + }); + + afterEach(() => { + clock.restore(); + }); + it("onChange correctly passes a Date and never null when canClearSelection is false", () => { const onChange = sinon.spy(); const { getDay } = wrap(); @@ -845,6 +855,19 @@ describe("", () => { assert.equal(value!.getFullYear(), today.getFullYear()); }); + it("selects the current day in the given timezone when Today is clicked", () => { + const { root } = wrap(); + root.find({ className: Classes.DATEPICKER_FOOTER }).find(Button).first().simulate("click"); + + const value = root.state("value")!; + assert.isNotNull(value); + assert.equal(value.getDate(), MOCK_TODAY.getDate() + 1); + assert.equal(value.getMonth(), MOCK_TODAY.getMonth()); + assert.equal(value.getFullYear(), MOCK_TODAY.getFullYear()); + assert.equal(value.getHours(), 1); + assert.equal(value.getMinutes(), 30); + }); + it("clears the value when Clear is clicked", () => { const { getDay, root } = wrap(); getDay().simulate("click");