Skip to content

Commit

Permalink
Merge pull request #1299 from iamkun/dev
Browse files Browse the repository at this point in the history
D2M
  • Loading branch information
iamkun authored Jan 3, 2021
2 parents fb3dd1b + bc53b53 commit 5471943
Show file tree
Hide file tree
Showing 14 changed files with 431 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ English | [简体中文](./docs/zh-cn/README.zh-CN.md) | [日本語](./docs/ja/R
alt="Day.js"></a></p>
<p align="center">Fast <b>2kB</b> alternative to Moment.js with the same modern API</p>
<p align="center">
<a href="https://www.duohui.cn?utm_source=dayjs" title="多会 - 专业活动管理系统" target="_blank"><img height="120px" alt="多会" src="https://user-images.githubusercontent.com/17680888/97983132-c433bd80-1e0f-11eb-8dde-9f216e05ee8a.png"/></a></p>
<a href="https://www.duohui.cn?utm_source=dayjs" title="多会 - 专业活动管理系统" target="_blank"><img height="120px" width="120px" alt="多会" src="https://user-images.githubusercontent.com/17680888/97983132-c433bd80-1e0f-11eb-8dde-9f216e05ee8a.png"/></a></p>
<p align="center">
<a href="https://unpkg.com/dayjs/dayjs.min.js"><img
src="http://img.badgesize.io/https://unpkg.com/dayjs/dayjs.min.js?compression=gzip&style=flat-square"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "2KB immutable date time library alternative to Moment.js with the same modern API ",
"main": "dayjs.min.js",
"types": "index.d.ts",
"module": "dayjs.min.js",
"module": "esm/index.js",
"scripts": {
"test": "TZ=Pacific/Auckland npm run test-tz && TZ=Europe/London npm run test-tz && TZ=America/Whitehorse npm run test-tz && npm run test-tz && jest",
"test-tz": "date && jest test/timezone.test --coverage=false",
Expand Down
2 changes: 1 addition & 1 deletion src/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ export const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ'
export const INVALID_DATE_STRING = 'Invalid Date'

// regex
export const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d+)?$/
export const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?\.?(\d+)?$/
export const REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g
38 changes: 38 additions & 0 deletions src/locale/ar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@
import dayjs from 'dayjs'

const months = 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_')
const symbolMap = {
1: '١',
2: '٢',
3: '٣',
4: '٤',
5: '٥',
6: '٦',
7: '٧',
8: '٨',
9: '٩',
0: '٠'
}

const numberMap = {
'١': '1',
'٢': '2',
'٣': '3',
'٤': '4',
'٥': '5',
'٦': '6',
'٧': '7',
'٨': '8',
'٩': '9',
'٠': '0'
}

const locale = {
name: 'ar',
Expand All @@ -26,6 +51,19 @@ const locale = {
y: 'عام واحد',
yy: '%d أعوام'
},
preparse(string) {
return string
.replace(
/[١٢٣٤٥٦٧٨٩٠]/g,
match => numberMap[match]
)
.replace(/،/g, ',')
},
postformat(string) {
return string
.replace(/\d/g, match => symbolMap[match])
.replace(/,/g, '،')
},
ordinal: n => n,
formats: {
LT: 'HH:mm',
Expand Down
6 changes: 4 additions & 2 deletions src/plugin/localeData/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export default (o, c, dayjs) => { // locale needed later
weekdaysShort: instance =>
(instance ? instance.format('ddd') : getShort(this, 'weekdaysShort', 'weekdays', 3)),
longDateFormat: format => getLongDateFormat(this.$locale(), format),
meridiem: this.$locale().meridiem
meridiem: this.$locale().meridiem,
ordinal: this.$locale().ordinal
}
}
proto.localeData = function () {
Expand All @@ -46,7 +47,8 @@ export default (o, c, dayjs) => { // locale needed later
months: () => dayjs.months(),
monthsShort: () => dayjs.monthsShort(),
longDateFormat: format => getLongDateFormat(localeObject, format),
meridiem: localeObject.meridiem
meridiem: localeObject.meridiem,
ordinal: localeObject.ordinal
}
}

Expand Down
47 changes: 47 additions & 0 deletions src/plugin/preParsePostFormat/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Plugin template from https://day.js.org/docs/en/plugin/plugin
export default (option, dayjsClass) => {
const oldParse = dayjsClass.prototype.parse
dayjsClass.prototype.parse = function (cfg) {
if (typeof cfg.date === 'string') {
const locale = this.$locale()
cfg.date =
locale && locale.preparse ? locale.preparse(cfg.date) : cfg.date
}
// original parse result
return oldParse.bind(this)(cfg)
}

// // overriding existing API
// // e.g. extend dayjs().format()
const oldFormat = dayjsClass.prototype.format
dayjsClass.prototype.format = function (...args) {
// original format result
const result = oldFormat.call(this, ...args)
// return modified result
const locale = this.$locale()
return locale && locale.postformat ? locale.postformat(result) : result
}

const oldFromTo = dayjsClass.prototype.fromToBase

if (oldFromTo) {
dayjsClass.prototype.fromToBase = function (
input,
withoutSuffix,
instance,
isFrom
) {
const locale = this.$locale() || instance.$locale()

// original format result
return oldFromTo.call(
this,
input,
withoutSuffix,
instance,
isFrom,
locale && locale.postformat
)
}
}
}
12 changes: 10 additions & 2 deletions src/plugin/relativeTime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default (o, c, d) => {
yy: '%d years'
}
d.en.relativeTime = relObj
const fromTo = (input, withoutSuffix, instance, isFrom) => {
proto.fromToBase = (input, withoutSuffix, instance, isFrom, postFormat) => {
const loc = instance.$locale().relativeTime || relObj
const T = o.thresholds || [
{ l: 's', r: 44, d: C.S },
Expand All @@ -46,11 +46,14 @@ export default (o, c, d) => {
? d(input).diff(instance, t.d, true)
: instance.diff(input, t.d, true)
}
const abs = (o.rounding || Math.round)(Math.abs(result))
let abs = (o.rounding || Math.round)(Math.abs(result))
isFuture = result > 0
if (abs <= t.r || !t.r) {
if (abs <= 1 && i > 0) t = T[i - 1] // 1 minutes -> a minute, 0 seconds -> 0 second
const format = loc[t.l]
if (postFormat) {
abs = postFormat(`${abs}`)
}
if (typeof format === 'string') {
out = format.replace('%d', abs)
} else {
Expand All @@ -66,6 +69,11 @@ export default (o, c, d) => {
}
return pastOrFuture.replace('%s', out)
}

function fromTo(input, withoutSuffix, instance, isFrom) {
return proto.fromToBase(input, withoutSuffix, instance, isFrom)
}

proto.to = function (input, withoutSuffix) {
return fromTo(input, withoutSuffix, this, true)
}
Expand Down
52 changes: 52 additions & 0 deletions test/locale/ar.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import moment from 'moment'
import MockDate from 'mockdate'
import dayjs from '../../src'
import relativeTime from '../../src/plugin/relativeTime'
import preParsePostFormat from '../../src/plugin/preParsePostFormat'
import localeData from '../../src/plugin/localeData'
import '../../src/locale/ar'

dayjs.extend(localeData)
dayjs.extend(relativeTime)
dayjs.extend(preParsePostFormat)

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})

it('Format Month with locale function', () => {
for (let i = 0; i <= 7; i += 1) {
const dayjsAR = dayjs().locale('ar').add(i, 'day')
const momentAR = moment().locale('ar').add(i, 'day')
const testFormat1 = 'DD MMMM YYYY MMM'
const testFormat2 = 'MMMM'
const testFormat3 = 'MMM'
expect(dayjsAR.format(testFormat1)).toEqual(momentAR.format(testFormat1))
expect(dayjsAR.format(testFormat2)).toEqual(momentAR.format(testFormat2))
expect(dayjsAR.format(testFormat3)).toEqual(momentAR.format(testFormat3))
}
})

it('Preparse with locale function', () => {
for (let i = 0; i <= 7; i += 1) {
dayjs.locale('ar')
const momentAR = moment().locale('ar').add(i, 'day')
expect(dayjs(momentAR.format()).format()).toEqual(momentAR.format())
}
})

it('RelativeTime: Time from X gets formatted', () => {
const T = [
[44.4, 'second', 'منذ ثانية واحدة']
]

T.forEach((t) => {
dayjs.locale('ar')
expect(dayjs().from(dayjs().add(t[0], t[1])))
.toBe(t[2])
})
})
45 changes: 45 additions & 0 deletions test/locale/ja.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import MockDate from 'mockdate'
import moment from 'moment'
import dayjs from '../../src'
import relativeTime from '../../src/plugin/relativeTime'
import '../../src/locale/ja'

dayjs.extend(relativeTime)

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})

it('Finnish locale relative time in past and future', () => {
const cases = [
[1, 'd', '1日後'],
[-1, 'd', '1日前'],
[2, 'd', '2日後'],
[-2, 'd', '2日前'],
[10, 'd', '10日後'],
[-10, 'd', '10日前'],
[6, 'm', '6分後'],
[-6, 'm', '6分前'],
[5, 'h', '5時間後'],
[-5, 'h', '5時間前'],
[3, 'M', '3ヶ月後'],
[-3, 'M', '3ヶ月前'],
[4, 'y', '4年後'],
[-4, 'y', '4年前']
]
cases.forEach((c) => {
expect(dayjs().add(c[0], c[1]).locale('ja').fromNow())
.toBe(c[2])
expect(dayjs().add(c[0], c[1]).locale('ja').fromNow())
.toBe(moment().add(c[0], c[1]).locale('ja').fromNow())
})
expect(dayjs().add(-10, 'd').locale('ja').fromNow(true))
.toBe('10日')
expect(dayjs().add(-10, 'd').locale('ja').fromNow(true))
.toBe(moment().add(-10, 'd').locale('ja').fromNow(true))
})

45 changes: 45 additions & 0 deletions test/parse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,49 @@ describe('REGEX_PARSE', () => {
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d.join('-')).toBe('2019-03-25T06:41:00.999999999-2019-03-25-06-41-00-999999999')
})
it('20210102T012345', () => {
const date = '20210102T012345'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d.join('-')).toBe('20210102T012345-2021-01-02-01-23-45-')
})
it('2021-01-02T01:23', () => {
const date = '2021-01-02T01:23'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d.join('-')).toBe('2021-01-02T01:23-2021-01-02-01-23--')
})
it('2021-01-02T01:23:45', () => {
const date = '2021-01-02T01:23:45'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d.join('-')).toBe('2021-01-02T01:23:45-2021-01-02-01-23-45-')
})

it('2020-12-31T18:00:00.000-0500 (no regex match)', () => {
const date = '2020-12-31T18:00:00.000-0500'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d).toBe(null)
})

it('2020-12-31T18:00:00-05:00 (no regex match)', () => {
const date = '2020-12-31T18:00:00-05:00'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d).toBe(null)
})

it('2021-01-02T01:23:45-0500 (no regex match)', () => {
const date = '2021-01-02T01:23:45-0500'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d).toBe(null)
})
it('2021-01-02T01:23:45Z (no regex match)', () => {
const date = '2021-01-02T01:23:45Z'
const d = date.match(REGEX_PARSE)
expect(dayjs(date).valueOf()).toBe(moment(date).valueOf())
expect(d).toBe(null)
})
})
7 changes: 7 additions & 0 deletions test/plugin/localeData.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,10 @@ it('meridiem', () => {
expect(typeof dayjs().localeData().meridiem).toEqual('function')
dayjs.locale('en')
})

it('ordinal', () => {
dayjs.locale('zh-cn')
expect(typeof dayjs.localeData().ordinal).toEqual('function')
expect(typeof dayjs().localeData().ordinal).toEqual('function')
dayjs.locale('en')
})
Loading

0 comments on commit 5471943

Please sign in to comment.