diff --git a/package.json b/package.json index ed5a9d570..d8a7061b4 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,12 @@ "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", + "date-fns": "^2.15.0", + "dayjs": "^1.8.30", "moment": "^2.24.0", "rc-trigger": "^4.0.0", "rc-util": "^5.0.1", + "react": "^16.0.0", "shallowequal": "^1.1.0" }, "engines": { @@ -58,7 +61,6 @@ "@umijs/fabric": "^2.0.8", "coveralls": "^3.0.6", "cross-env": "^7.0.2", - "dayjs": "^1.8.18", "enzyme": "^3.0.0", "enzyme-adapter-react-16": "^1.0.1", "enzyme-to-json": "^3.4.0", @@ -72,16 +74,10 @@ "mockdate": "^3.0.2", "np": "^6.2.3", "prettier": "^2.0.5", - "react": "^16.0.0", "react-dom": "^16.0.0", "react-test-renderer": "^16.0.0", "typescript": "^3.7.2" }, - "peerDependencies": { - "dayjs": "^1.8.18", - "react": "^16.0.0", - "react-dom": "^16.0.0" - }, "cnpm": { "mode": "npm" }, diff --git a/src/generate/dateFns.ts b/src/generate/dateFns.ts new file mode 100644 index 000000000..e201e2379 --- /dev/null +++ b/src/generate/dateFns.ts @@ -0,0 +1,87 @@ +import { + getDay, + getYear, + getMonth, + getDate, + getHours, + getMinutes, + getSeconds, + addYears, + addMonths, + addDays, + setYear, + setMonth, + setDate, + setHours, + setMinutes, + setSeconds, + isAfter, + isValid, + getWeek, + format as formatDate, + parse as parseDate, +} from 'date-fns'; +import * as Locale from 'date-fns/locale'; +import { GenerateConfig } from '.'; + +const dealLocal = (str: string) => { + return str.replace(/_/g, ''); +}; + +const generateConfig: GenerateConfig = { + // get + getNow: () => new Date(), + getWeekDay: date => getDay(date), + getYear: date => getYear(date), + getMonth: date => getMonth(date), + getDate: date => getDate(date), + getHour: date => getHours(date), + getMinute: date => getMinutes(date), + getSecond: date => getSeconds(date), + + // set + addYear: (date, diff) => addYears(date, diff), + addMonth: (date, diff) => addMonths(date, diff), + addDate: (date, diff) => addDays(date, diff), + setYear: (date, year) => setYear(date, year), + setMonth: (date, month) => setMonth(date, month), + setDate: (date, num) => setDate(date, num), + setHour: (date, hour) => setHours(date, hour), + setMinute: (date, minute) => setMinutes(date, minute), + setSecond: (date, second) => setSeconds(date, second), + + // Compare + isAfter: (date1, date2) => isAfter(date1, date2), + isValidate: date => isValid(date), + + locale: { + getWeekFirstDay: locale => { + const clone = Locale[dealLocal(locale)]; + return clone.options.weekStartsOn; + }, + getWeek: (locale, date) => { + return getWeek(date, { locale: Locale[dealLocal(locale)] }); + }, + format: (locale, date, format) => { + if (!isValid(date)) { + return null; + } + return formatDate(date, format, { locale: Locale[dealLocal(locale)] }); + }, + parse: (locale, text, formats) => { + for (let i = 0; i < formats.length; i += 1) { + const format = formats[i]; + const formatText = text; + const date = parseDate(formatText, format, new Date(), { + locale: Locale[dealLocal(locale)], + }); + if (isValid(date)) { + return date; + } + } + return null; + }, + }, +}; + +export default generateConfig; diff --git a/tests/generate.spec.tsx b/tests/generate.spec.tsx index 9510a524b..cf55e27af 100644 --- a/tests/generate.spec.tsx +++ b/tests/generate.spec.tsx @@ -1,6 +1,7 @@ import MockDate from 'mockdate'; import momentGenerateConfig from '../src/generate/moment'; import dayjsGenerateConfig from '../src/generate/dayjs'; +import dateFnsGenerateConfig from '../src/generate/dateFns'; import { getMoment } from './util/commonUtil'; import 'dayjs/locale/zh-cn'; @@ -18,6 +19,7 @@ describe('Picker.Generate', () => { const list: { name: string; generateConfig: GenerateConfig }[] = [ { name: 'moment', generateConfig: momentGenerateConfig }, { name: 'dayjs', generateConfig: dayjsGenerateConfig }, + { name: 'date-fns', generateConfig: dateFnsGenerateConfig }, ]; list.forEach(({ name, generateConfig }) => { @@ -42,7 +44,8 @@ describe('Picker.Generate', () => { date = generateConfig.setMinute(date, 3); date = generateConfig.setSecond(date, 5); - expect(generateConfig.locale.format('en_US', date, 'YYYY-MM-DD HH:mm:ss')).toEqual( + const formatStr = name === 'date-fns' ? 'yyyy-MM-dd HH:mm:ss' : 'YYYY-MM-DD HH:mm:ss'; + expect(generateConfig.locale.format('en_US', date, formatStr)).toEqual( '2020-10-23 02:03:05', ); }); @@ -52,7 +55,8 @@ describe('Picker.Generate', () => { date = generateConfig.addYear(date, 2); date = generateConfig.addMonth(date, 2); date = generateConfig.addDate(date, 2); - expect(generateConfig.locale.format('en_US', date, 'YYYY-MM-DD')).toEqual('1992-11-05'); + const formatStr = name === 'date-fns' ? 'yyyy-MM-dd' : 'YYYY-MM-DD'; + expect(generateConfig.locale.format('en_US', date, formatStr)).toEqual('1992-11-05'); }); it('isAfter', () => { @@ -70,43 +74,44 @@ describe('Picker.Generate', () => { describe('locale', () => { describe('parse', () => { it('basic', () => { + const formatStr1 = name === 'date-fns' ? 'yyyy-MM-dd' : 'YYYY-MM-DD'; + const formatStr2 = name === 'date-fns' ? 'dd/mm/yyyy' : 'DD/MM/YYYY'; ['2000-01-02', '02/01/2000'].forEach(str => { - const date = generateConfig.locale.parse('en_US', str, ['YYYY-MM-DD', 'DD/MM/YYYY']); + const date = generateConfig.locale.parse('en_US', str, [formatStr1, formatStr2]); - expect(generateConfig.locale.format('en_US', date!, 'YYYY-MM-DD')).toEqual( + expect(generateConfig.locale.format('en_US', date!, formatStr1)).toEqual( '2000-01-02', ); }); }); it('week', () => { - expect( - generateConfig.locale.format( - 'en_US', - generateConfig.locale.parse('en_US', '2019-1st', ['gggg-wo'])!, - 'gggg-wo', - ), - ).toEqual('2019-1st'); - - expect( - generateConfig.locale.format( - 'zh_CN', - generateConfig.locale.parse('zh_CN', '2019-45周', ['gggg-wo'])!, - 'gggg-wo', - ), - ).toEqual('2019-45周'); - }); - }); - }); - - describe('locale', () => { - it('parse', () => { - ['2000-01-02', '02/01/2000'].forEach(str => { - const date = generateConfig.locale.parse('en_US', str, ['YYYY-MM-DD', 'DD/MM/YYYY']); - - expect(generateConfig.locale.format('en_US', date!, 'YYYY-MM-DD')).toEqual( - '2000-01-02', - ); + const formatStr = name === 'date-fns' ? 'GGGG-wo' : 'gggg-wo'; + if (name !== 'date-fns') { + expect( + generateConfig.locale.format( + 'en_US', + generateConfig.locale.parse('en_US', '2019-1st', [formatStr])!, + formatStr, + ), + ).toEqual('2019-1st'); + + expect( + generateConfig.locale.format( + 'zh_CN', + generateConfig.locale.parse('zh_CN', '2019-45周', [formatStr])!, + formatStr, + ), + ).toEqual('2019-45周'); + } else { + expect( + generateConfig.locale.format( + 'en_US', + generateConfig.locale.parse('en_US', '2019-1st', [formatStr])!, + formatStr, + ), + ).toEqual(null); + } }); }); }); @@ -115,23 +120,26 @@ describe('Picker.Generate', () => { expect(generateConfig.locale.getWeekFirstDay('en_US')).toEqual(0); expect(generateConfig.locale.getWeekFirstDay('zh_CN')).toEqual(1); + const formatStr = name === 'date-fns' ? 'yyyy-MM-dd' : 'YYYY-MM-DD'; // Should keep same weekday ['en_US', 'zh_CN'].forEach(() => { expect( generateConfig.getWeekDay( - generateConfig.locale.parse('en_US', '2000-01-01', ['YYYY-MM-DD'])!, + generateConfig.locale.parse('en_US', '2000-01-01', [formatStr])!, ), ).toEqual(6); }); }); it('Parse format Wo', () => { - expect( - generateConfig.locale.parse('en_US', '2012-51st', ['YYYY-Wo'])?.format('Wo'), - ).toEqual('51st'); - expect(generateConfig.locale.parse('zh_CN', '2012-1周', ['YYYY-Wo'])?.format('Wo')).toEqual( - '1周', - ); + if (name !== 'date-fns') { + expect( + generateConfig.locale.parse('en_US', '2012-51st', ['YYYY-Wo']).format('Wo'), + ).toEqual('51st'); + expect( + generateConfig.locale.parse('zh_CN', '2012-1周', ['YYYY-Wo']).format('Wo'), + ).toEqual('1周'); + } }); it('Parse format faild', () => { @@ -143,78 +151,72 @@ describe('Picker.Generate', () => { ).toEqual(null); }); - it('getShortWeekDays', () => { - expect(generateConfig.locale.getShortWeekDays!('zh_CN')).toEqual([ - '日', - '一', - '二', - '三', - '四', - '五', - '六', - ]); - expect(generateConfig.locale.getShortWeekDays!('en_US')).toEqual([ - 'Su', - 'Mo', - 'Tu', - 'We', - 'Th', - 'Fr', - 'Sa', - ]); - }); - - it('getShortMonths', () => { - expect(generateConfig.locale.getShortMonths!('zh_CN')).toEqual([ - '1月', - '2月', - '3月', - '4月', - '5月', - '6月', - '7月', - '8月', - '9月', - '10月', - '11月', - '12月', - ]); - expect(generateConfig.locale.getShortMonths!('en_US')).toEqual([ - 'Jan', - 'Feb', - 'Mar', - 'Apr', - 'May', - 'Jun', - 'Jul', - 'Aug', - 'Sep', - 'Oct', - 'Nov', - 'Dec', - ]); - }); + if (name !== 'date-fns') { + it('getShortWeekDays', () => { + expect(generateConfig.locale.getShortWeekDays!('zh_CN')).toEqual([ + '日', + '一', + '二', + '三', + '四', + '五', + '六', + ]); + expect(generateConfig.locale.getShortWeekDays!('en_US')).toEqual([ + 'Su', + 'Mo', + 'Tu', + 'We', + 'Th', + 'Fr', + 'Sa', + ]); + }); - it('getWeek', () => { - expect( - generateConfig.locale.getWeek( - 'zh_CN', - generateConfig.locale.parse('zh_CN', '2019-12-08', ['YYYY-MM-DD'])!, - ), - ).toEqual(49); - }); + it('getShortMonths', () => { + expect(generateConfig.locale.getShortMonths!('zh_CN')).toEqual([ + '1月', + '2月', + '3月', + '4月', + '5月', + '6月', + '7月', + '8月', + '9月', + '10月', + '11月', + '12月', + ]); + expect(generateConfig.locale.getShortMonths!('en_US')).toEqual([ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]); + }); + } it('getWeek', () => { + const formatStr = name === 'date-fns' ? 'yyyy-MM-dd' : 'YYYY-MM-DD'; expect( generateConfig.locale.getWeek( 'zh_CN', - generateConfig.locale.parse('zh_CN', '2019-12-08', ['YYYY-MM-DD'])!, + generateConfig.locale.parse('zh_CN', '2019-12-08', [formatStr]), ), ).toEqual(49); expect( generateConfig.locale.getWeek( 'en_US', - generateConfig.locale.parse('en_US', '2019-12-08', ['YYYY-MM-DD'])!, + generateConfig.locale.parse('en_US', '2019-12-08', [formatStr]), ), ).toEqual(50); });