Skip to content

Commit

Permalink
fix: strftime getSuffix works for all dates
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jgarber623 authored and harttle committed Jun 15, 2023
1 parent e401a30 commit 0b4e2a9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 15 deletions.
29 changes: 23 additions & 6 deletions src/util/strftime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
})

Expand Down
33 changes: 24 additions & 9 deletions src/util/strftime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 0b4e2a9

Please sign in to comment.