fix: strftime getSuffix works for all dates

As written, the strftime module's `getSuffix` method (responsible for
returning a date's ordinal string) works correctly for all dates in a
month _except_ 11, 12, and 13.

The existing code would return a string based on the last digit of the
date. In American English, these three dates use the `th` suffix rather
than `st`, `nd`, or `rd`.

This refactor/bug fix draws inspiration from Rails' ActiveSupport
ordinal inflector:

https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.rb

The Ruby code above is designed to work with any number, so the bug fix
to this library is simpler.

The test suite is also updated with additional examples to verify the
correctness of these changes.
This commit is contained in:
Jason Garber
2023-06-15 21:01:55 +08:00
committed by Jun Yang
parent e401a30972
commit 0b4e2a9979
2 changed files with 47 additions and 15 deletions
+23 -6
View File
@@ -32,13 +32,30 @@ describe('util/strftime', function () {
})
})
it('should format %q as date suffix', function () {
const st = new Date('2016-03-01 03:05:03')
const nd = new Date('2016-03-02 03:05:03')
const rd = new Date('2016-03-03 03:05:03')
expect(t(st, '%q')).toBe('st')
expect(t(nd, '%q')).toBe('nd')
expect(t(rd, '%q')).toBe('rd')
const first = new Date('2016-03-01 03:05:03')
const second = new Date('2016-03-02 03:05:03')
const third = new Date('2016-03-03 03:05:03')
const eleventh = new Date('2016-03-11 03:05:03')
const twelfth = new Date('2016-03-12 03:05:03')
const thirteenth = new Date('2016-03-13 03:05:03')
const twentyfirst = new Date('2016-03-21 03:05:03')
const twentysecond = new Date('2016-03-22 03:05:03')
const twentythird = new Date('2016-03-23 03:05:03')
expect(t(first, '%q')).toBe('st')
expect(t(second, '%q')).toBe('nd')
expect(t(third, '%q')).toBe('rd')
expect(t(now, '%q')).toBe('th')
expect(t(eleventh, '%q')).toBe('th')
expect(t(twelfth, '%q')).toBe('th')
expect(t(thirteenth, '%q')).toBe('th')
expect(t(twentyfirst, '%q')).toBe('st')
expect(t(twentysecond, '%q')).toBe('nd')
expect(t(twentythird, '%q')).toBe('rd')
})
})
+24 -9
View File
@@ -11,12 +11,6 @@ const dayNames = [
]
const monthNamesShort = monthNames.map(abbr)
const dayNamesShort = dayNames.map(abbr)
const suffixes = {
1: 'st',
2: 'nd',
3: 'rd',
'default': 'th'
}
interface FormatOptions {
flags: object;
width?: string;
@@ -52,9 +46,30 @@ function isLeapYear (d: LiquidDate) {
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
}
function getSuffix (d: LiquidDate) {
const str = d.getDate().toString()
const index = parseInt(str.slice(-1))
return suffixes[index] || suffixes['default']
const date = d.getDate()
let suffix = 'th'
switch (date) {
case 11:
case 12:
case 13:
break
default:
switch (date % 10) {
case 1:
suffix = 'st'
break
case 2:
suffix = 'nd'
break
case 3:
suffix = 'rd'
break
}
}
return suffix
}
function century (d: LiquidDate) {
return parseInt(d.getFullYear().toString().substring(0, 2), 10)