diff --git a/src/index.js b/src/index.js index 0afb1830..ccd0a95e 100644 --- a/src/index.js +++ b/src/index.js @@ -278,14 +278,15 @@ class Dayjs { const str = formatStr || C.FORMAT_DEFAULT const zoneStr = Utils.z(this) const locale = this.$locale() + const { $H, $m, $M } = this const { weekdays, months, meridiem } = locale const getShort = (arr, index, full, length) => ( - (arr && arr[index]) || full[index].substr(0, length) + (arr && (arr[index] || arr(this, str))) || full[index].substr(0, length) ) const get$H = num => ( - Utils.s(this.$H % 12 || 12, num, '0') + Utils.s($H % 12 || 12, num, '0') ) const meridiemFunc = meridiem || ((hour, minute, isLowercase) => { @@ -295,32 +296,32 @@ class Dayjs { const matches = { YY: String(this.$y).slice(-2), - YYYY: String(this.$y), - M: String(this.$M + 1), - MM: Utils.s(this.$M + 1, 2, '0'), - MMM: getShort(locale.monthsShort, this.$M, months, 3), - MMMM: months[this.$M], - D: String(this.$D), + YYYY: this.$y, + M: $M + 1, + MM: Utils.s($M + 1, 2, '0'), + MMM: getShort(locale.monthsShort, $M, months, 3), + MMMM: months[$M] || months(this, str), + D: this.$D, DD: Utils.s(this.$D, 2, '0'), - d: String(this.$W), + d: this.$W, dd: getShort(locale.weekdaysMin, this.$W, weekdays, 2), ddd: getShort(locale.weekdaysShort, this.$W, weekdays, 3), dddd: weekdays[this.$W], - H: String(this.$H), - HH: Utils.s(this.$H, 2, '0'), + H: $H, + HH: Utils.s($H, 2, '0'), h: get$H(1), hh: get$H(2), - a: meridiemFunc(this.$H, this.$m, true), - A: meridiemFunc(this.$H, this.$m, false), - m: String(this.$m), - mm: Utils.s(this.$m, 2, '0'), - s: String(this.$s), + a: meridiemFunc($H, $m, true), + A: meridiemFunc($H, $m, false), + m: $m, + mm: Utils.s($m, 2, '0'), + s: this.$s, ss: Utils.s(this.$s, 2, '0'), SSS: Utils.s(this.$ms, 3, '0'), Z: zoneStr // 'ZZ' logic below } - return str.replace(C.REGEX_FORMAT, (match, $1) => $1 || matches[match] || zoneStr.replace(':', '')) // 'ZZ' + return String(str.replace(C.REGEX_FORMAT, (match, $1) => $1 || matches[match] || zoneStr.replace(':', ''))) // 'ZZ' } utcOffset() { diff --git a/src/locale/ru.js b/src/locale/ru.js index d629283a..d8911c71 100644 --- a/src/locale/ru.js +++ b/src/locale/ru.js @@ -1,12 +1,29 @@ import dayjs from 'dayjs' +const monthFormat = 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') +const monthStandalone = 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_') + +const monthShortFormat = 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_') +const monthShortStandalone = 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_') + +const MONTHS_IN_FORMAT = /D[oD]?(\[[^[\]]*\]|\s)+MMMM?/ const locale = { name: 'ru', weekdays: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), weekdaysShort: 'вск_пнд_втр_срд_чтв_птн_сбт'.split('_'), weekdaysMin: 'вс_пн_вт_ср_чт_пт_сб'.split('_'), - months: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), - monthsShort: 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.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()] + }, weekStart: 1, formats: { LT: 'H:mm', diff --git a/test/locale/keys.test.js b/test/locale/keys.test.js index 327eb02a..a06960a3 100644 --- a/test/locale/keys.test.js +++ b/test/locale/keys.test.js @@ -35,11 +35,23 @@ Locale.forEach((locale) => { expect(weekdays).toEqual(expect.any(Array)) if (weekdaysShort) expect(weekdaysShort).toEqual(expect.any(Array)) - if (monthsShort) expect(monthsShort).toEqual(expect.any(Array)) if (weekdaysMin) expect(weekdaysMin).toEqual(expect.any(Array)) if (weekStart) expect(weekStart).toEqual(expect.any(Number)) - expect(months).toEqual(expect.any(Array)) + // months could be a function or array + if (Array.isArray(months)) { + expect(months).toEqual(expect.any(Array)) + } else { + expect(months(dayjs(), 'str')).toEqual(expect.any(String)) + } + // 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)) + } + } // function pass date return string or number or null if (name !== 'en') { // en ordinal set in advancedFormat for (let i = 1; i <= 31; i += 1) { diff --git a/test/locale/ru.test.js b/test/locale/ru.test.js new file mode 100644 index 00000000..3960c78d --- /dev/null +++ b/test/locale/ru.test.js @@ -0,0 +1,25 @@ +import moment from 'moment' +import MockDate from 'mockdate' +import dayjs from '../../src' +import '../../src/locale/ru' + +beforeEach(() => { + MockDate.set(new Date()) +}) + +afterEach(() => { + MockDate.reset() +}) + +it('Format Month with locale function', () => { + for (let i = 0; i <= 7; i += 1) { + const dayjsRU = dayjs().locale('ru').add(i, 'day') + const momentRU = moment().locale('ru').add(i, 'day') + const testFormat1 = 'DD MMMM YYYY MMM' + const testFormat2 = 'MMMM' + const testFormat3 = 'MMM' + expect(dayjsRU.format(testFormat1)).toEqual(momentRU.format(testFormat1)) + expect(dayjsRU.format(testFormat2)).toEqual(momentRU.format(testFormat2)) + expect(dayjsRU.format(testFormat3)).toEqual(momentRU.format(testFormat3)) + } +})