A simple, functional, and cross-browser solution for converting between time zones and converting a date to a string with a selected time zone:
export function convertTimeZone(
date: Date,
timeZoneFrom?: string | null, // default timezone is Local
timeZoneTo?: string | null, // default timezone is Local
): Date {
const dateFrom = timeZoneFrom == null
? date
: new Date(
date.toLocaleString('en-US', {
timeZone: timeZoneFrom,
}),
)
const dateTo = timeZoneTo == null
? date
: new Date(
date.toLocaleString('en-US', {
timeZone: timeZoneTo,
}),
)
const result = new Date(date.getTime() + dateTo.getTime() - dateFrom.getTime())
return result
}
export function dateToString(date: Date, timeZone: string): string {
date = convertTimeZone(date, 'UTC', timeZone)
const year = date.getUTCFullYear().toString().padStart(4, '0')
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0')
const day = date.getUTCDate().toString().padStart(2, '0')
const hours = date.getUTCHours().toString().padStart(2, '0')
const minutes = date.getUTCMinutes().toString().padStart(2, '0')
const seconds = date.getUTCSeconds().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
Tests
describe('date', function () {
it('convertTimeZone', function () {
// UTC => UTC
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), 'UTC', 'UTC'))
.toEqual(new Date('2020-01-01T00:00:00.000Z'))
// UTC => Europe/Kiev
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), 'UTC', 'Europe/Kiev'))
.toEqual(new Date('2020-01-01T02:00:00.000Z'))
// Europe/Kiev => UTC
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), 'Europe/Kiev', 'UTC'))
.toEqual(new Date('2019-12-31T22:00:00.000Z'))
// Europe/Kiev => America/Los_Angeles
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), 'Europe/Kiev', 'America/Los_Angeles'))
.toEqual(new Date('2019-12-31T14:00:00.000Z'))
// America/Los_Angeles => Europe/Kiev
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), 'America/Los_Angeles', 'Europe/Kiev'))
.toEqual(new Date('2020-01-01T10:00:00.000Z'))
// Local => Local
expect(convertTimeZone(new Date('2020-01-01T00:00:00.000Z'), null, null))
.toEqual(new Date('2020-01-01T00:00:00.000Z'))
// forward and backward for timezone list
const timeZones = [
null, // Local
'UTC',
'Europe/Kiev',
'America/Los_Angeles',
'America/New_York',
'America/Chicago',
'America/Denver',
'Europe/London',
'Europe/Paris',
'Europe/Moscow',
'Europe/Berlin',
'Asia/Tokyo',
'Asia/Shanghai',
'Asia/Hong_Kong',
'Asia/Kolkata',
'Australia/Sydney',
'Australia/Melbourne',
'Australia/Perth',
'Australia/Brisbane',
]
for (const timeZoneFrom of timeZones) {
for (const timeZoneTo of timeZones) {
const date = new Date('2020-01-01T00:00:00.000Z')
const result = convertTimeZone(date, timeZoneFrom, timeZoneTo)
const resultBack = convertTimeZone(result, timeZoneTo, timeZoneFrom)
expect(resultBack).toEqual(date)
}
}
})
it('dateToString', function () {
expect(dateToString(new Date('2020-01-01T00:00:00.000Z'), 'UTC'))
.toEqual('2020-01-01 00:00:00')
expect(dateToString(new Date('2020-01-01T00:00:00.000Z'), 'Europe/Kiev'))
.toEqual('2020-01-01 02:00:00')
expect(dateToString(new Date('2020-01-01T00:00:00.000Z'), 'America/Los_Angeles'))
.toEqual('2019-12-31 16:00:00')
expect(dateToString(new Date('2020-01-01T00:00:00.000Z'), 'America/New_York'))
.toEqual('2019-12-31 19:00:00')
})
it('dateToString current', function () {
console.log(`Current date UTC: ${dateToString(new Date(), 'UTC')}`)
console.log(`Current date Europe/Kiev: ${dateToString(new Date(), 'Europe/Kiev')}`)
console.log(`Current date America/Los_Angeles: ${dateToString(new Date(), 'America/Los_Angeles')}`)
})
})