diff --git a/core/src/components/datetime/test/data.spec.ts b/core/src/components/datetime/test/data.spec.ts index a851992e89..959ed25456 100644 --- a/core/src/components/datetime/test/data.spec.ts +++ b/core/src/components/datetime/test/data.spec.ts @@ -333,15 +333,12 @@ describe('getToday', () => { beforeAll(() => { jest.useFakeTimers('modern'); // System time is zero based, 1 = February - jest.setSystemTime(new Date(2022, 1, 21)); + jest.setSystemTime(new Date(2022, 1, 21, 18, 30)); }); - it('should return today', () => { + it('should return today without converting to UTC time', () => { const res = getToday(); - const expected = new Date(); - expected.setHours(expected.getHours() - expected.getTimezoneOffset() / 60); - - expect(res).toEqual('2022-02-21T00:00:00.000Z'); + expect(res).toEqual('2022-02-21T18:30:00.000Z'); }); }); diff --git a/core/src/components/datetime/utils/data.ts b/core/src/components/datetime/utils/data.ts index 853cc44962..77f0c8f6d6 100644 --- a/core/src/components/datetime/utils/data.ts +++ b/core/src/components/datetime/utils/data.ts @@ -8,42 +8,48 @@ import { getNextMonth, getPreviousMonth } from './manipulation'; /** * Returns the current date as * an ISO string in the user's - * timezone. + * time zone. */ export const getToday = () => { /** - * Grab the current date object - * as well as the timezone offset - */ - const date = new Date(); - const tzOffset = date.getTimezoneOffset(); - - /** - * When converting to ISO string, everything is - * set to UTC. Since we want to show these dates - * relative to the user's timezone, we need to - * subtract the timezone offset from the date - * so that when `toISOString()` adds it back - * there was a net change of zero hours from the - * local date. - */ - const adjustedHours = date.getHours() - tzOffset / 60; - - /** - * Some timezones include minute adjustments - * such as 30 or 45 minutes. + * ion-datetime intentionally does not + * parse time zones/do automatic time zone + * conversion when accepting user input. + * However when we get today's date string, + * we want it formatted relative to the user's + * time zone. + * + * When calling toISOString(), the browser + * will convert the date to UTC time by either adding + * or subtracting the time zone offset. + * To work around this, we need to either add + * or subtract the time zone offset to the Date + * object prior to calling toISOString(). + * This allows us to get an ISO string + * that is in the user's time zone. + * + * Example: + * Time zone offset is 240 + * Meaning: The browser needs to add 240 minutes + * to the Date object to get UTC time. + * What Ionic does: We subtract 240 minutes + * from the Date object. The browser then adds + * 240 minutes in toISOString(). The result + * is a time that is in the user's time zone + * and not UTC. + * + * Note: Some timezones include minute adjustments + * such as 30 or 45 minutes. This is why we use setMinutes + * instead of setHours. * Example: India Standard Time * Timezone offset: -330 = -5.5 hours. * - * As a result, we need to make sure we also - * increment the minutes as well. * List of timezones with 30 and 45 minute timezones: * https://www.timeanddate.com/time/time-zones-interesting.html */ - const minutesRemainder = adjustedHours % 1; - const adjustedMinutes = date.getMinutes() + minutesRemainder * 60; - date.setHours(adjustedHours); - date.setMinutes(adjustedMinutes); + const date = new Date(); + const tzOffset = date.getTimezoneOffset(); + date.setMinutes(date.getMinutes() - tzOffset); return date.toISOString(); };