chore(datetime): simpler way of doing timezone offsets (#25132)

This commit is contained in:
Liam DeBeasi
2022-04-15 19:27:27 +05:45
committed by GitHub
parent 90115db985
commit 46cd483aa1
2 changed files with 36 additions and 33 deletions

View File

@ -333,15 +333,12 @@ describe('getToday', () => {
beforeAll(() => { beforeAll(() => {
jest.useFakeTimers('modern'); jest.useFakeTimers('modern');
// System time is zero based, 1 = February // 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 res = getToday();
const expected = new Date(); expect(res).toEqual('2022-02-21T18:30:00.000Z');
expected.setHours(expected.getHours() - expected.getTimezoneOffset() / 60);
expect(res).toEqual('2022-02-21T00:00:00.000Z');
}); });
}); });

View File

@ -8,42 +8,48 @@ import { getNextMonth, getPreviousMonth } from './manipulation';
/** /**
* Returns the current date as * Returns the current date as
* an ISO string in the user's * an ISO string in the user's
* timezone. * time zone.
*/ */
export const getToday = () => { export const getToday = () => {
/** /**
* Grab the current date object * ion-datetime intentionally does not
* as well as the timezone offset * parse time zones/do automatic time zone
*/ * conversion when accepting user input.
const date = new Date(); * However when we get today's date string,
const tzOffset = date.getTimezoneOffset(); * we want it formatted relative to the user's
* time zone.
/** *
* When converting to ISO string, everything is * When calling toISOString(), the browser
* set to UTC. Since we want to show these dates * will convert the date to UTC time by either adding
* relative to the user's timezone, we need to * or subtracting the time zone offset.
* subtract the timezone offset from the date * To work around this, we need to either add
* so that when `toISOString()` adds it back * or subtract the time zone offset to the Date
* there was a net change of zero hours from the * object prior to calling toISOString().
* local date. * This allows us to get an ISO string
*/ * that is in the user's time zone.
const adjustedHours = date.getHours() - tzOffset / 60; *
* Example:
/** * Time zone offset is 240
* Some timezones include minute adjustments * Meaning: The browser needs to add 240 minutes
* such as 30 or 45 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 * Example: India Standard Time
* Timezone offset: -330 = -5.5 hours. * 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: * List of timezones with 30 and 45 minute timezones:
* https://www.timeanddate.com/time/time-zones-interesting.html * https://www.timeanddate.com/time/time-zones-interesting.html
*/ */
const minutesRemainder = adjustedHours % 1; const date = new Date();
const adjustedMinutes = date.getMinutes() + minutesRemainder * 60; const tzOffset = date.getTimezoneOffset();
date.setHours(adjustedHours); date.setMinutes(date.getMinutes() - tzOffset);
date.setMinutes(adjustedMinutes);
return date.toISOString(); return date.toISOString();
}; };