Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Advanced format output with short offset name #2637

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions src/plugin/timezone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,36 @@ const typeToPos = {
// Cache time-zone lookups from Intl.DateTimeFormat,
// as it is a *very* slow method.
const dtfCache = {}
const getDateTimeFormat = (timezone, options = {}) => {
const timeZoneName = options.timeZoneName || 'short'
const key = `${timezone}|${timeZoneName}`
let dtf = dtfCache[key]
const getDateTimeFormat = (timeZone) => {
/* Long output is always correct whatever the timezone.
* and whatever the locale, en-US / en-GB etc...
* We will extract the short version ourself
*/
let dtf = dtfCache[timeZone]
if (!dtf) {
dtf = new Intl.DateTimeFormat('en-US', {
hour12: false,
timeZone: timezone,
timeZone,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName
timeZoneName: 'long'
})
dtfCache[key] = dtf

dtfCache[timeZone] = dtf
}
return dtf
}

export default (o, c, d) => {
let defaultTimezone

const makeFormatParts = (timestamp, timezone, options = {}) => {
const makeFormatParts = (timestamp, timezone) => {
const date = new Date(timestamp)
const dtf = getDateTimeFormat(timezone, options)
const dtf = getDateTimeFormat(timezone)
return dtf.formatToParts(date)
}

Expand Down Expand Up @@ -107,11 +110,21 @@ export default (o, c, d) => {
return ins
}

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this PR together, I found it really helpful! 🎉

There's a small issue where the value for Istanbul is 'GMT+03:00' so the returned abbreviation becomes G.

Maybe you could add a check to see if there are any digits in the value and then return the value instead of abbreviating it?

result.value = result.value.split(' ').map(v => v[0]).join('')
}
cachedOffsetName[cacheKey] = result.value
this.$x.$offsetName = cachedOffsetName
return result.value
}

const oldStartOf = proto.startOf
Expand Down
16 changes: 16 additions & 0 deletions test/plugin/advancedFormat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,22 @@ it('Format offsetName z zzz', () => {
expect(dayjs().format('zzz')).toBeDefined()
})

it('Format offsetName z zzz with Europe/Berlin timeZone', () => {
const dtz = dayjs().tz('Europe/Berlin')
expect(dtz.format('z')).toBe('CEST')
expect(dtz.format('zzz')).toBe('Central European Summer Time')
expect(dayjs().format('z')).toBeDefined()
expect(dayjs().format('zzz')).toBeDefined()
})

it('Format offsetName z zzz with Asia/Kolkata timeZone', () => {
const dtz = dayjs.tz('2012-03-11 01:59:59', 'Asia/Kolkata')
expect(dtz.format('z')).toBe('IST')
expect(dtz.format('zzz')).toBe('India 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
Loading