Skip to content

Instantly share code, notes, and snippets.

@jeffsheets
Last active November 5, 2021 02:49
Show Gist options
  • Save jeffsheets/710d1d6dd2f2acb0125a5d624ae915e4 to your computer and use it in GitHub Desktop.
Save jeffsheets/710d1d6dd2f2acb0125a5d624ae915e4 to your computer and use it in GitHub Desktop.
Browser Javascript to get user timezone or offset that is IE11 safe when passed to a Java API, with Jest Test blogpost: https://www.sheetsj.com/2021/05/mock-intl-and-date-globals-in-jest.html
/**
* Useful when passing the browser timezone to a backend Java API that reads a timezone in using ZoneId.of(tz),
* as both 'America/Chicago' and '-0600' are valid values when passed to the Java API.
* The Offset is used to handle IE11 and other older browsers.
*/
export const getUserTimeZoneOrOffset = () => {
let timeZone;
try {
timeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (error) {
// Ignore if this happens, and just use the fallback
}
if (!timeZone) {
//Could not get a browser timezone, maybe IE11, so instead use timezoneOffset formatted for Java
// https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/ZoneOffset.html#of(java.lang.String)
const offset = new Date().getTimezoneOffset();
//Yeah this offset +/- seems backwards,
// but JS actually returns a positive when local tz is behind UTC (like for US tzs)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
// e.g. offset = 300, timeZone='-0500'
const plusMinus = offset <= 0 ? '+' : '-';
//leftpad a 0 when needed for two digits
const hours = ('0' + Math.floor(Math.abs(offset) / 60)).slice(-2);
const minutes = ('0' + (offset % 60)).slice(-2);
timeZone = `${plusMinus}${hours}${minutes}`;
}
return timeZone;
};
import { getUserTimeZoneOrOffset } from './timeZoneUtils.js';
describe('getUserTimeZoneOrOffset', () => {
let mockOffset;
let mockTimezone;
beforeEach(() => {
mockTimezone = undefined;
jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(() => ({
resolvedOptions: () => ({
timeZone: mockTimezone
})
}));
mockOffset = undefined;
jest
.spyOn(Date.prototype, 'getTimezoneOffset')
.mockImplementation(() => mockOffset);
});
afterEach(() => {
jest.restoreAllMocks();
});
test('returns timezone name when found', () => {
mockTimezone = 'America/Chicago';
const result = getUserTimeZoneOrOffset();
expect(result).toBe('America/Chicago');
});
test.each([
[300, '-0500'],
[150, '-0230'],
[-60, '+0100'],
[-330, '+0530'],
[0, '+0000'],
[-765, '+1245']
])('timezoneOffset for %i is %s', (offset, expected) => {
mockOffset = offset;
const result = getUserTimeZoneOrOffset();
expect(result).toBe(expected);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment