Skip to content

Commit

Permalink
fix: update timezone plugin to support getting offset name e.g. EST (#…
Browse files Browse the repository at this point in the history
…1069)

* fix: update timezone plugin to support getting offset name e.g. EST

* chore: typo
  • Loading branch information
zazzaz authored Sep 25, 2020
1 parent 3d73543 commit cbb755e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 9 deletions.
6 changes: 5 additions & 1 deletion src/plugin/advancedFormat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default (o, c, d) => { // locale needed later
const locale = this.$locale()
const utils = this.$utils()
const str = formatStr || FORMAT_DEFAULT
const result = str.replace(/\[([^\]]+)]|Q|wo|ww|w|gggg|Do|X|x|k{1,2}|S/g, (match) => {
const result = str.replace(/\[([^\]]+)]|Q|wo|ww|w|zzz|z|gggg|Do|X|x|k{1,2}|S/g, (match) => {
switch (match) {
case 'Q':
return Math.ceil((this.$M + 1) / 3)
Expand All @@ -33,6 +33,10 @@ export default (o, c, d) => { // locale needed later
return Math.floor(this.$d.getTime() / 1000)
case 'x':
return this.$d.getTime()
case 'z':
return `[${this.offsetName()}]`
case 'zzz':
return `[${this.offsetName('long')}]`
default:
return match
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugin/duration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Duration {

calMilliseconds() {
this.$ms = Object.keys(this.$d).reduce((total, unit) => (
total + ((this.$d[unit] || 0) * (unitToMS[unit] || 1))
total + ((this.$d[unit] || 0) * (unitToMS[unit]))
), 0)
}

Expand Down Expand Up @@ -106,7 +106,7 @@ class Duration {
}

as(unit) {
return this.$ms / (unitToMS[prettyUnit(unit)] || 1)
return this.$ms / (unitToMS[prettyUnit(unit)])
}

get(unit) {
Expand Down
29 changes: 23 additions & 6 deletions src/plugin/timezone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export default (o, c, d) => {
let defaultTimezone

const localUtcOffset = d().utcOffset()
const tzOffset = (timestamp, timezone) => {

const makeFormatParts = (timestamp, timezone, option = {}) => {
const date = new Date(timestamp)
const dtf = new Intl.DateTimeFormat('en-US', {
hour12: false,
Expand All @@ -23,9 +24,14 @@ export default (o, c, d) => {
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
second: '2-digit',
timeZoneName: option.timeZoneName || 'short'
})
const formatResult = dtf.formatToParts(date)
return dtf.formatToParts(date)
}

const tzOffset = (timestamp, timezone) => {
const formatResult = makeFormatParts(timestamp, timezone)
const filled = []
for (let i = 0; i < formatResult.length; i += 1) {
const { type, value } = formatResult[i]
Expand All @@ -35,13 +41,14 @@ export default (o, c, d) => {
filled[pos] = parseInt(value, 10)
}
}
const hour = filled[3]
// Workaround for the same behavior in different node version
// https://github.com/nodejs/node/issues/33027
const hour = filled[3]
/* istanbul ignore next */
const fixedHour = hour === 24 ? 0 : hour
const utcString = `${filled[0]}-${filled[1]}-${filled[2]} ${fixedHour}:${filled[4]}:${filled[5]}:000`
const utcTs = d.utc(utcString).valueOf()
let asTS = +date
let asTS = +timestamp
const over = asTS % 1000
asTS -= over
return (utcTs - asTS) / (60 * 1000)
Expand Down Expand Up @@ -76,7 +83,16 @@ export default (o, c, d) => {
proto.tz = function (timezone = defaultTimezone) {
const target = this.toDate().toLocaleString('en-US', { timeZone: timezone })
const diff = Math.round((this.toDate() - new Date(target)) / 1000 / 60)
return d(target).utcOffset(localUtcOffset - diff, true).$set(ms, this.$ms)
const ins = d(target).utcOffset(localUtcOffset - diff, true).$set(ms, this.$ms)
ins.$x.$timezone = timezone
return ins
}

proto.offsetName = function (type) {
// type: short(default) / long
const zone = this.$x.$timezone || d.tz.guess()
const result = makeFormatParts(this.valueOf(), zone, { timeZoneName: type }).find(m => m.type.toLowerCase() === 'timezonename')
return result && result.value
}

d.tz = function (input, timezone = defaultTimezone) {
Expand All @@ -89,6 +105,7 @@ export default (o, c, d) => {
localTs = localTs || d.utc(input).valueOf()
const [targetTs, targetOffset] = fixOffset(localTs, previousOffset, timezone)
const ins = d(targetTs).utcOffset(targetOffset)
ins.$x.$timezone = timezone
return ins
}

Expand Down
12 changes: 12 additions & 0 deletions test/plugin/advancedFormat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import dayjs from '../../src'
import advancedFormat from '../../src/plugin/advancedFormat'
import weekOfYear from '../../src/plugin/weekOfYear'
import weekYear from '../../src/plugin/weekYear'
import timezone from '../../src/plugin/timezone'
import utc from '../../src/plugin/utc'
import '../../src/locale/zh-cn'

dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(weekYear)
dayjs.extend(weekOfYear)
dayjs.extend(advancedFormat)
Expand Down Expand Up @@ -83,6 +87,14 @@ it('Format Week Year gggg', () => {
expect(dayjs(d).format('gggg')).toBe(moment(d).format('gggg'))
})

it('Format offsetName z zzz', () => {
const dtz = dayjs.tz('2012-03-11 01:59:59', 'America/New_York')
expect(dtz.format('z')).toBe('EST')
expect(dtz.format('zzz')).toBe('Eastern Standard Time')
expect(dayjs().format('z')).toBeDefined()
expect(dayjs().format('zzz')).toBeDefined()
})

it('Skips format strings inside brackets', () => {
expect(dayjs().format('[Q]')).toBe('Q')
expect(dayjs().format('[Do]')).toBe('Do')
Expand Down
14 changes: 14 additions & 0 deletions test/plugin/timezone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,17 @@ describe('set Default', () => {
expect(tokyo.valueOf()).toBe(1401591600000)
})
})

describe('Get offsetName', () => {
const dtz = dayjs.tz('2012-03-11 01:59:59', NY)
it('short', () => {
const d = dtz.offsetName('short')
const m = moment.tz('2012-03-11 01:59:59', NY).format('z')
expect(d).toBe(m)
expect(d).toBe('EST')
})
it('long', () => {
const d = dtz.offsetName('long')
expect(d).toBe('Eastern Standard Time')
})
})

0 comments on commit cbb755e

Please sign in to comment.