Skip to content

Commit

Permalink
Merge pull request #909 from iamkun/dev
Browse files Browse the repository at this point in the history
D2M
  • Loading branch information
iamkun authored May 14, 2020
2 parents c95be8a + 8593932 commit 04224ae
Show file tree
Hide file tree
Showing 12 changed files with 599 additions and 28 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
36 changes: 36 additions & 0 deletions src/locale/rw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Kinyarwanda (Rwanda) [rw]
import dayjs from 'dayjs'

const locale = {
name: 'rw',
weekdays: 'Ku Cyumweru_Kuwa Mbere_Kuwa Kabiri_Kuwa Gatatu_Kuwa Kane_Kuwa Gatanu_Kuwa Gatandatu'.split('_'),
months: 'Mutarama_Gashyantare_Werurwe_Mata_Gicurasi_Kamena_Nyakanga_Kanama_Nzeri_Ukwakira_Ugushyingo_Ukuboza'.split('_'),
relativeTime: {
future: 'mu %s',
past: '%s',
s: 'amasegonda',
m: 'Umunota',
mm: '%d iminota',
h: 'isaha',
hh: '%d amasaha',
d: 'Umunsi',
dd: '%d iminsi',
M: 'ukwezi',
MM: '%d amezi',
y: 'umwaka',
yy: '%d imyaka'
},
formats: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'DD/MM/YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY HH:mm',
LLLL: 'dddd, D MMMM YYYY HH:mm'
},
ordinal: n => n
}

dayjs.locale(locale, null, true)

export default locale
40 changes: 40 additions & 0 deletions src/locale/tk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Turkmen [tk]
import dayjs from 'dayjs'

const locale = {
name: 'tk',
weekdays: 'Ýekşenbe_Duşenbe_Sişenbe_Çarşenbe_Penşenbe_Anna_Şenbe'.split('_'),
weekdaysShort: 'Ýek_Duş_Siş_Çar_Pen_Ann_Şen'.split('_'),
weekdaysMin: 'Ýk_Dş_Sş_Çr_Pn_An_Şn'.split('_'),
months: 'Ýanwar_Fewral_Mart_Aprel_Maý_Iýun_Iýul_Awgust_Sentýabr_Oktýabr_Noýabr_Dekabr'.split('_'),
monthsShort: 'Ýan_Few_Mar_Apr_Maý_Iýn_Iýl_Awg_Sen_Okt_Noý_Dek'.split('_'),
weekStart: 1,
formats: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'DD.MM.YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY HH:mm',
LLLL: 'dddd, D MMMM YYYY HH:mm'
},
relativeTime: {
future: '%s soň',
past: '%s öň',
s: 'birnäçe sekunt',
m: 'bir minut',
mm: '%d minut',
h: 'bir sagat',
hh: '%d sagat',
d: 'bir gün',
dd: '%d gün',
M: 'bir aý',
MM: '%d aý',
y: 'bir ýyl',
yy: '%d ýyl'
},
ordinal: n => `${n}.`
}

dayjs.locale(locale, null, true)

export default locale
39 changes: 29 additions & 10 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 Expand Up @@ -196,11 +202,24 @@ export default (o, C, d) => {
locale = pl ? d.Ls[pl] : this.$locale()
}
this.$d = parseFormattedInput(date, format, utc)
this.init(cfg)
this.init()
if (pl && pl !== true) this.$L = this.locale(pl).$L
if (isStrict && date !== this.format(format)) {
this.$d = new Date('')
}
if (pl && pl !== true) this.$L = pl
} else if (format instanceof Array) {
const len = format.length
for (let i = 1; i <= len; i += 1) {
args[1] = format[i - 1]
const result = d.apply(this, args)
if (result.isValid()) {
this.$d = result.$d
this.$L = result.$L
this.init()
break
}
if (i === len) this.$d = new Date('')
}
} else {
oldParse.call(this, cfg)
}
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
63 changes: 63 additions & 0 deletions src/plugin/objectSupport/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
export default (o, c) => {
const proto = c.prototype
const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array) && obj instanceof Object
const prettyUnit = (u) => {
const unit = proto.$utils().p(u)
return unit === 'date' ? 'day' : unit
}
const parseDate = (cfg) => {
const { date, utc } = cfg
const $d = {}
if (isObject(date)) {
Object.keys(date).forEach((k) => {
$d[prettyUnit(k)] = date[k]
})
const y = $d.year || 1970
const M = $d.month - 1 || 0
const d = $d.day || 1
const h = $d.hour || 0
const m = $d.minute || 0
const s = $d.second || 0
const ms = $d.millisecond || 0
if (utc) {
return new Date(Date.UTC(y, M, d, h, m, s, ms))
}
return new Date(y, M, d, h, m, s, ms)
}
return date
}

const oldParse = proto.parse
proto.parse = function (cfg) {
cfg.date = parseDate.bind(this)(cfg)
oldParse.bind(this)(cfg)
}

const oldSet = proto.set
const oldAdd = proto.add

const callObject = function (call, argument, string, offset = 1) {
if (argument instanceof Object) {
const keys = Object.keys(argument)
let chain = this
keys.forEach((key) => {
chain = call.bind(chain)(argument[key] * offset, key)
})
return chain
}
return call.bind(this)(argument * offset, string)
}

proto.set = function (string, int) {
int = int === undefined ? string : int
return callObject.bind(this)(function (i, s) {
return oldSet.bind(this)(s, i)
}, int, string)
}
proto.add = function (number, string) {
return callObject.bind(this)(oldAdd, number, string)
}
proto.subtract = function (number, string) {
return callObject.bind(this)(oldAdd, number, string, -1)
}
}
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
34 changes: 34 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,20 @@ it('correctly parse ordinal', () => {
.toBe(momentCN.locale())
})

describe('month function locale', () => {
it('MMMM', () => {
const input = '08 мая 2020'
const input2 = '08 май 2020'
const format = 'DD MMMM YYYY'
expect(dayjs(input, format, 'ru').valueOf()).toBe(moment(input, format, 'ru').valueOf())
expect(dayjs(input2, format, 'ru').valueOf()).toBe(moment(input2, 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 All @@ -248,3 +263,22 @@ describe('Strict mode', () => {
expect(dayjs(input, format, 'zh-cn', true).isValid()).toBe(false)
})
})

describe('Array format support', () => {
it('second ok', () => {
const input = '2012-05-28'
const format = ['YYYY', 'YYYY-MM-DD']
expect(dayjs(input, format).isValid()).toBe(true)
expect(dayjs(input, format, true).format('YYYY-MM-DD')).toBe('2012-05-28')
})
it('all invalid', () => {
const input = '2012-05-28'
const format = ['DD', 'MM-DD']
expect(dayjs(input, format, true).isValid()).toBe(false)
})
it('with locale', () => {
const input = '2018 三月 12'
const format = ['YYYY', 'MM', 'YYYY MMMM DD']
expect(dayjs(input, format, 'zh-cn', true).format('YYYY MMMM DD')).toBe(input)
})
})
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())
})
Loading

0 comments on commit 04224ae

Please sign in to comment.