Support date format in locale (#14340)

* use locale format

* remove monthFormat

* use locale format

* add test case
This commit is contained in:
zombieJ 2019-01-15 16:58:40 +08:00 committed by GitHub
parent 307c877a02
commit 04111fb40e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 281 additions and 9 deletions

View File

@ -973,3 +973,214 @@ exports[`MonthPicker and WeekPicker render WeekPicker 1`] = `
</div>
</div>
`;
exports[`Picker format by locale date 1`] = `
<span
class="ant-calendar-picker"
>
<div>
<input
class="ant-calendar-picker-input ant-input"
placeholder="请选择日期"
readonly=""
value="2000 年 1 月 1 日"
/>
<i
aria-label="图标: close-circle"
class="anticon anticon-close-circle ant-calendar-picker-clear"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</i>
<i
aria-label="图标: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
aria-hidden="true"
class=""
data-icon="calendar"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
/>
</svg>
</i>
</div>
</span>
`;
exports[`Picker format by locale dateTime 1`] = `
<span
class="ant-calendar-picker"
style="width: 195px;"
>
<div>
<input
class="ant-calendar-picker-input ant-input"
placeholder="请选择日期"
readonly=""
value="2000 年 1 月 1 日 0 时 0 分 0 秒"
/>
<i
aria-label="图标: close-circle"
class="anticon anticon-close-circle ant-calendar-picker-clear"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</i>
<i
aria-label="图标: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
aria-hidden="true"
class=""
data-icon="calendar"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
/>
</svg>
</i>
</div>
</span>
`;
exports[`Picker format by locale month 1`] = `
<span
class="ant-calendar-picker"
>
<div>
<input
class="ant-calendar-picker-input ant-input"
placeholder="请选择日期"
readonly=""
value="2000 年 1 月"
/>
<i
aria-label="图标: close-circle"
class="anticon anticon-close-circle ant-calendar-picker-clear"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</i>
<i
aria-label="图标: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
aria-hidden="true"
class=""
data-icon="calendar"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
/>
</svg>
</i>
</div>
</span>
`;
exports[`Picker format by locale week 1`] = `
<span
class="ant-calendar-picker"
>
<span
style="display: inline-block; width: 100%;"
>
<input
class="ant-calendar-picker-input ant-input"
placeholder="请选择日期"
readonly=""
value="2000 年 52 周"
/>
<i
aria-label="图标: close-circle"
class="anticon anticon-close-circle ant-calendar-picker-clear"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="close-circle"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
/>
</svg>
</i>
<i
aria-label="图标: calendar"
class="anticon anticon-calendar ant-calendar-picker-icon"
>
<svg
aria-hidden="true"
class=""
data-icon="calendar"
fill="currentColor"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
/>
</svg>
</i>
</span>
</span>
`;

View File

@ -2,9 +2,42 @@ import React from 'react';
import { mount, render } from 'enzyme';
import moment from 'moment';
import DatePicker from '..';
import LocaleProvider from '../../locale-provider';
import locale from '../../locale-provider/zh_CN';
const { MonthPicker, WeekPicker } = DatePicker;
describe('Picker format by locale', () => {
const myLocale = {
...locale,
DatePicker: {
...locale.DatePicker,
dateFormat: 'YYYY 年 M 月 D 日',
dateTimeFormat: 'YYYY 年 M 月 D 日 H 时 m 分 s 秒',
weekFormat: 'YYYY 年 W 周',
monthFormat: 'YYYY 年 M 月',
},
};
const date = moment('2000-01-01', 'YYYY-MM-DD');
function matchPicker(name, Picker, props) {
it(name, () => {
const wrapper = mount(
<LocaleProvider locale={myLocale}>
<Picker value={date} {...props} />
</LocaleProvider>,
);
expect(wrapper.render()).toMatchSnapshot();
});
}
matchPicker('date', DatePicker);
matchPicker('dateTime', DatePicker, { showTime: true });
matchPicker('week', WeekPicker);
matchPicker('month', MonthPicker);
});
describe('MonthPicker and WeekPicker', () => {
it('render MonthPicker', () => {
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');

View File

@ -31,7 +31,6 @@ ReactDOM.render(
<div>
<DatePicker
showTime
format="YYYY-MM-DD HH:mm:ss"
placeholder="Select Time"
onChange={onChange}
onOk={onOk}

View File

@ -7,16 +7,16 @@ import RangePicker from './RangePicker';
import WeekPicker from './WeekPicker';
import { DatePickerProps, DatePickerDecorator } from './interface';
const DatePicker = wrapPicker(createPicker(RcCalendar)) as React.ClassicComponentClass<
const DatePicker = wrapPicker(createPicker(RcCalendar), 'date') as React.ClassicComponentClass<
DatePickerProps
>;
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'YYYY-MM');
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'month');
Object.assign(DatePicker, {
RangePicker: wrapPicker(RangePicker),
RangePicker: wrapPicker(RangePicker, 'date'),
MonthPicker,
WeekPicker: wrapPicker(WeekPicker, 'gggg-wo'),
WeekPicker: wrapPicker(WeekPicker, 'week'),
});
export default DatePicker as DatePickerDecorator;

View File

@ -31,5 +31,9 @@
},
"timePickerLocale": {
"placeholder": "Select time"
}
},
"dateFormat": "YYYY-MM-DD",
"dateTimeFormat": "YYYY-MM-DD HH:mm:ss",
"weekFormat": "YYYY-wo",
"monthFormat": "YYYY-MM"
}

View File

@ -6,6 +6,25 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { generateShowHourMinuteSecond } from '../time-picker';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
type PickerType = 'date' | 'week' | 'month';
interface PickerMap {
[name: string]: string;
}
const DEFAULT_FORMAT: PickerMap = {
date: 'YYYY-MM-DD',
week: 'gggg-wo',
month: 'YYYY-MM',
};
const LOCALE_FORMAT_MAPPING: PickerMap = {
date: 'dateFormat',
dateTime: 'dateTimeFormat',
week: 'weekFormat',
month: 'monthFormat',
};
function getColumns({ showHour, showMinute, showSecond, use12Hours }: any) {
let column = 0;
if (showHour) {
@ -23,10 +42,9 @@ function getColumns({ showHour, showMinute, showSecond, use12Hours }: any) {
return column;
}
export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFormat?: string): any {
export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType: PickerType): any {
return class PickerWrapper extends React.Component<any, any> {
static defaultProps = {
format: defaultFormat || 'YYYY-MM-DD',
transitionName: 'slide-up',
popupStyle: {},
onChange() {},
@ -102,6 +120,13 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
};
renderPicker = (locale: any, localeCode: string) => {
const { format, showTime } = this.props;
const mergedPickerType = showTime ? `${pickerType}Time` : pickerType;
const mergedFormat =
format ||
locale[LOCALE_FORMAT_MAPPING[mergedPickerType]] ||
DEFAULT_FORMAT[mergedPickerType];
return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
@ -110,7 +135,6 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
inputPrefixCls: customizeInputPrefixCls,
size,
disabled,
showTime,
} = this.props;
const prefixCls = getPrefixCls('calendar', customizePrefixCls);
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
@ -145,6 +169,7 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
return (
<Picker
{...this.props}
format={mergedFormat}
ref={this.savePicker}
pickerClass={pickerClass}
pickerInputClass={pickerInputClass}