Skip to content

Commit

Permalink
fix: Fix locale month function bug (#908)
Browse files Browse the repository at this point in the history
  • Loading branch information
iamkun authored May 14, 2020
1 parent 97856c6 commit bf347c3
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class Dayjs {
M: $M + 1,
MM: Utils.s($M + 1, 2, '0'),
MMM: getShort(locale.monthsShort, $M, months, 3),
MMMM: months[$M] || months(this, str),
MMMM: getShort(months, $M),
D: this.$D,
DD: Utils.s(this.$D, 2, '0'),
d: String(this.$W),
Expand Down
31 changes: 19 additions & 12 deletions src/locale/ru.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,31 @@ function relativeTimeWithPlural(number, withoutSuffix, key) {

return `${number} ${plural(format[key], +number)}`
}
const months = (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()]
}
return monthStandalone[dayjsInstance.month()]
}
months.s = monthStandalone
months.f = monthFormat

const monthsShort = (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthShortFormat[dayjsInstance.month()]
}
return monthShortStandalone[dayjsInstance.month()]
}
monthsShort.s = monthShortStandalone
monthsShort.f = monthShortFormat

const locale = {
name: 'ru',
weekdays: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
weekdaysShort: 'вск_пнд_втр_срд_чтв_птн_сбт'.split('_'),
weekdaysMin: 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
months: (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()]
}
return monthStandalone[dayjsInstance.month()]
},
monthsShort: (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthShortFormat[dayjsInstance.month()]
}
return monthShortStandalone[dayjsInstance.month()]
},
months,
monthsShort,
weekStart: 1,
formats: {
LT: 'H:mm',
Expand Down
22 changes: 14 additions & 8 deletions src/plugin/customParseFormat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const matchUpperCaseAMPM = /[AP]M/
const matchLowerCaseAMPM = /[ap]m/
const matchSigned = /[+-]?\d+/ // -inf - inf
const matchOffset = /[+-]\d\d:?\d\d/ // +00:00 -00:00 +0000 or -0000
const matchWord = /\d*[^\s\d-:/.()]+/ // Word
const matchWord = /\d*[^\s\d-:/()]+/ // Word

let locale

Expand All @@ -30,6 +30,13 @@ const zoneExpressions = [matchOffset, function (input) {
zone.offset = offsetFromString(input)
}]

const getLocalePart = (name) => {
const part = locale[name]
return part && (
part.indexOf ? part : part.s.concat(part.f)
)
}

const expressions = {
A: [matchUpperCaseAMPM, function (input) {
this.afternoon = input === 'PM'
Expand Down Expand Up @@ -69,22 +76,21 @@ const expressions = {
M: [match1to2, addInput('month')],
MM: [match2, addInput('month')],
MMM: [matchWord, function (input) {
const { months, monthsShort } = locale
const matchIndex = monthsShort
? monthsShort.findIndex(month => month === input)
: months.findIndex(month => month.substr(0, 3) === input)
const months = getLocalePart('months')
const monthsShort = getLocalePart('monthsShort')
const matchIndex = (monthsShort || months.map(_ => _.substr(0, 3))).indexOf(input)
if (matchIndex < 0) {
throw new Error()
}
this.month = matchIndex + 1
this.month = (matchIndex + 1) % 12
}],
MMMM: [matchWord, function (input) {
const { months } = locale
const months = getLocalePart('months')
const matchIndex = months.indexOf(input)
if (matchIndex < 0) {
throw new Error()
}
this.month = matchIndex + 1
this.month = (matchIndex + 1) % 12
}],
Y: [matchSigned, addInput('year')],
YY: [match2, function (input) {
Expand Down
10 changes: 5 additions & 5 deletions src/plugin/localeData/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export default (o, c, dayjs) => { // locale needed later
const proto = c.prototype
const getLocalePart = part => (part && (part.indexOf ? part : part.s))
const getShort = (ins, target, full, num) => {
const locale = ins.name ? ins : ins.$locale()
if (!locale[target]) {
return locale[full].map(f => f.substr(0, num))
}
return locale[target]
const targetLocale = getLocalePart(locale[target])
const fullLocale = getLocalePart(locale[full])
return targetLocale || fullLocale.map(f => f.substr(0, num))
}
const getDayjsLocaleObject = () => dayjs.Ls[dayjs.locale()]
const localeData = function () {
Expand Down Expand Up @@ -38,7 +38,7 @@ export default (o, c, dayjs) => { // locale needed later
}
}

dayjs.months = () => getDayjsLocaleObject().months
dayjs.months = () => getShort(getDayjsLocaleObject(), 'months')

dayjs.monthsShort = () => getShort(getDayjsLocaleObject(), 'monthsShort', 'months', 3)

Expand Down
4 changes: 4 additions & 0 deletions test/locale/keys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ Locale.forEach((locale) => {
expect(months).toEqual(expect.any(Array))
} else {
expect(months(dayjs(), 'str')).toEqual(expect.any(String))
expect(months.f).toEqual(expect.any(Array))
expect(months.s).toEqual(expect.any(Array))
}
// monthsShort could be a function or array
if (monthsShort) {
if (Array.isArray(monthsShort)) {
expect(monthsShort).toEqual(expect.any(Array))
} else {
expect(monthsShort(dayjs(), 'str')).toEqual(expect.any(String))
expect(monthsShort.f).toEqual(expect.any(Array))
expect(monthsShort.s).toEqual(expect.any(Array))
}
}
// function pass date return string or number or null
Expand Down
13 changes: 13 additions & 0 deletions test/plugin/customParseFormat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dayjs from '../../src'
import customParseFormat from '../../src/plugin/customParseFormat'
import uk from '../../src/locale/uk'
import '../../src/locale/zh-cn'
import '../../src/locale/ru'

dayjs.extend(customParseFormat)

Expand Down Expand Up @@ -233,6 +234,18 @@ it('correctly parse ordinal', () => {
.toBe(momentCN.locale())
})

describe('month function locale', () => {
it('MMMM', () => {
const input = '08 мая 2020'
const format = 'DD MMMM YYYY'
expect(dayjs(input, format, 'ru').valueOf()).toBe(moment(input, format, 'ru').valueOf())
})
it('MMM', () => {
const input = '08 февр. 2020'
const format = 'DD MMM YYYY'
expect(dayjs(input, format, 'ru').valueOf()).toBe(moment(input, format, 'ru').valueOf())
})
})

describe('Strict mode', () => {
it('without locale', () => {
Expand Down
12 changes: 12 additions & 0 deletions test/plugin/localeData.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import localeData from '../../src/plugin/localeData'
import localizedFormat from '../../src/plugin/localizedFormat'
import '../../src/locale/fr'
import '../../src/locale/zh-cn'
import '../../src/locale/ru'

dayjs.extend(localizedFormat)
dayjs.extend(localeData)
Expand Down Expand Up @@ -65,3 +66,14 @@ it('Listing the months and weekdays', () => {
expect(dayjs.weekdaysMin()).toEqual(moment.weekdaysMin())
})
})

it('Month function', () => {
const dayjsLocaleData = dayjs().locale('ru').localeData()
const momentLocaleData = moment().locale('ru').localeData()
expect(dayjsLocaleData.months()).toEqual(momentLocaleData.months())
expect(dayjsLocaleData.monthsShort()).toEqual(momentLocaleData.monthsShort())
dayjs.locale('ru')
moment.locale('ru')
expect(dayjs.months()).toEqual(moment.months())
expect(dayjs.monthsShort()).toEqual(moment.monthsShort())
})

0 comments on commit bf347c3

Please sign in to comment.