Last active
November 5, 2021 02:49
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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