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(() => {
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');
});
});

View File

@ -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();
};