Skip to content

Commit

Permalink
Merge pull request #206 from github/strftime-localisation
Browse files Browse the repository at this point in the history
Strftime localisation
  • Loading branch information
keithamus authored Nov 21, 2022
2 parents a121747 + aac49ef commit 2a36937
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/relative-time-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat
if (!date) return
const format = this.format
if (format !== 'auto' && format !== 'micro' && format !== 'elapsed') {
return strftime(date, format)
return strftime(date, format, this.#lang)
} else if (format === 'elapsed') {
const precisionIndex = unitNames.indexOf(this.precision) || 0
const units = elapsedTime(date).filter(unit => unitNames.indexOf(unit[1]) >= precisionIndex)
Expand Down
23 changes: 22 additions & 1 deletion src/strftime.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const supportsIntlDatetime = 'Intl' in window && 'DateTimeFormat' in Intl

const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
const months = [
'January',
Expand All @@ -14,27 +16,46 @@ const months = [
'December'
]

export function strftime(time: Date, formatString: string): string {
export function strftime(time: Date, formatString: string, lang?: string): string {
const day = time.getDay()
const date = time.getDate()
const month = time.getMonth()
const year = time.getFullYear()
const hour = time.getHours()
const minute = time.getMinutes()
const second = time.getSeconds()
const useIntl = lang && supportsIntlDatetime
const shortParts = useIntl && new Intl.DateTimeFormat(lang, {weekday: 'short', month: 'short'}).formatToParts(time)
const longParts = useIntl && new Intl.DateTimeFormat(lang, {weekday: 'long', month: 'long'}).formatToParts(time)
return formatString.replace(/%([%aAbBcdeHIlmMpPSwyYZz])/g, function (_arg) {
let match
const modifier = _arg[1]
switch (modifier) {
case '%':
return '%'
case 'a':
if (shortParts) {
const weekdayPart = shortParts.find(part => part.type === 'weekday')
if (weekdayPart) return weekdayPart.value
}
return weekdays[day].slice(0, 3)
case 'A':
if (longParts) {
const weekdayPart = longParts.find(part => part.type === 'weekday')
if (weekdayPart) return weekdayPart.value
}
return weekdays[day]
case 'b':
if (shortParts) {
const monthPart = shortParts.find(part => part.type === 'month')
if (monthPart) return monthPart.value
}
return months[month].slice(0, 3)
case 'B':
if (longParts) {
const monthPart = longParts.find(part => part.type === 'month')
if (monthPart) return monthPart.value
}
return months[month]
case 'c':
return time.toString()
Expand Down
5 changes: 4 additions & 1 deletion test/relative-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ suite('relative-time', function () {
{datetime: '2022-10-24t14:46:00.000z', tense: 'auto', format: 'micro', expected: '1m'},
{datetime: '2022-10-24t14:46:00.000z', tense: 'auto', format: 'auto', expected: 'now'},
{datetime: '2022-10-24t14:46:00.000z', tense: 'auto', format: '%Y-%m-%d', expected: '2022-10-24'},
{datetime: '2022-10-24t14:46:00.000z', format: '%A %b %d', lang: 'es', expected: 'lunes oct 24'},
{datetime: '2022-10-24t14:46:00.000z', format: '%A %b %d', lang: 'pl', expected: 'poniedziałek paź 24'},

// Dates in the past
{datetime: '2022-09-24T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1m'},
Expand Down Expand Up @@ -775,14 +777,15 @@ suite('relative-time', function () {
}
])

for (const {datetime, expected, tense, format, precision = '', reference = referenceDate} of tests) {
for (const {datetime, expected, tense, format, precision = '', lang = null, reference = referenceDate} of tests) {
test(`<relative-time datetime="${datetime}" tense="${tense}" format="${format}"> => ${expected}`, function () {
freezeTime(new Date(reference))
const time = document.createElement('relative-time')
time.setAttribute('tense', tense)
time.setAttribute('datetime', datetime)
time.setAttribute('format', format)
time.setAttribute('precision', precision)
if (lang) time.setAttribute('lang', lang)
assert.equal(time.shadowRoot.textContent, expected)
})
}
Expand Down
16 changes: 16 additions & 0 deletions test/strftime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,20 @@ suite('strftime', function () {
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%${k}`), v)
})
}

test('supports multiple languages', () => {
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%a`, 'es'), 'mié')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%A`, 'es'), 'miércoles')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%a`, 'nl'), 'wo')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%A`, 'nl'), 'woensdag')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%a`, 'pl'), 'śr.')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%A`, 'pl'), 'środa')

assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%b`, 'es'), 'oct')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%B`, 'es'), 'octubre')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%b`, 'nl'), 'okt.')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%B`, 'nl'), 'oktober')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%b`, 'pl'), 'paź')
assert.equal(strftime(new Date('2022-10-19T11:31:59.554Z'), `%B`, 'pl'), 'październik')
})
})

0 comments on commit 2a36937

Please sign in to comment.