Skip to content

Commit

Permalink
feat: support timezone setting (#2102)
Browse files Browse the repository at this point in the history
Co-authored-by: YanHui <[email protected]>
  • Loading branch information
hiker90 and YanHui authored Oct 17, 2022
1 parent d95d90e commit 6f6d503
Show file tree
Hide file tree
Showing 17 changed files with 104 additions and 60 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
"@types/react-resizable": "^1.7.3",
"classnames": "^2.2.6",
"date-fns": "^2.21.3",
"date-fns-tz": "^1.3.7",
"immutability-helper": "^3.1.1",
"lodash": "^4.17.14",
"moment": "^2.26.0",
"moment-timezone": "^0.5.38",
"pinyin-match": "^1.2.2",
"raf": "^3.4.1",
"rc-animate": "^3.1.0",
Expand Down
4 changes: 2 additions & 2 deletions src/date-picker/Picker.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import classnames from 'classnames';
import { usePrefixCls, useControlledState } from '@gio-design/utils';
import { format } from 'date-fns/fp';
import { CalendarOutlined } from '@gio-design/icons';
import { parseFnsTimeZone } from '../utils/timeHelper'
import Popover from '../popover';
import { InputButton } from '../input';
import StaticDatePicker from '../static-date-picker';
Expand Down Expand Up @@ -38,7 +38,7 @@ export const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) =>

const [controlledValue, setControlledValue] = useControlledState(value, defaultValue);

const formatDate = (date: Date) => format(formatString, date);
const formatDate = (date: Date) => parseFnsTimeZone(date, formatString);

const handleVisibleChange = (current: boolean) => {
setVisible(current);
Expand Down
6 changes: 3 additions & 3 deletions src/date-picker/demos/DatePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/react/types-6-0';
import { withDesign } from 'storybook-addon-designs';
import { DownFilled } from '@gio-design/icons';
import { addMonths, isBefore, startOfToday } from 'date-fns';
import { format } from 'date-fns/fp';
import { parseFnsTimeZone } from '../../utils/timeHelper'
import Docs from './DatePickerPage';
import Button from '../../button';
import Toast from '../../toast';
Expand Down Expand Up @@ -84,9 +84,9 @@ export const ControlledStatic: Story = () => {
const [value, setValue] = useState(new Date(2022, 4, 0));
const [pickerMode, setMode] = useState('date');
return (<div>
<h3>pickerMode:{pickerMode},current value: {format('yyyy/MM/dd HH:MM:SS', value)}</h3>
<h3>pickerMode:{pickerMode},current value: {parseFnsTimeZone(value, 'yyyy/MM/dd HH:MM:SS')}</h3>
<DatePicker.Static value={value} onSelect={v => setValue(v)} viewDate={value} onPanelChange={(val, mode) => {
setMode(mode);
// setValue(val);
}} /></div>)
};
};
4 changes: 2 additions & 2 deletions src/date-range-picker/Picker.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from 'react';
import classnames from 'classnames';
import { usePrefixCls, useControlledState } from '@gio-design/utils';
import format from 'date-fns/format';
import { CalendarOutlined } from '@gio-design/icons';
import { parseFnsTimeZone } from '../utils/timeHelper'
import Popover from '../popover';
import { InputButton } from '../input';
import StaticDateRangePicker from '../static-date-range-picker';
import { DateRangePickerProps, NullableDate, NullableString } from './interfaces';

export const formatDates = (dates: [NullableDate, NullableDate], formatString = 'yyyy/MM/dd'): NullableString => {
const strongFormat = (date: NullableDate) => (date ? format(date, formatString) : undefined);
const strongFormat = (date: NullableDate) => (date ? parseFnsTimeZone(date, formatString) : undefined);
return `${strongFormat(dates[0]) || ''} - ${strongFormat(dates[1]) || ''}`;
};

Expand Down
11 changes: 6 additions & 5 deletions src/legacy/date-picker/DatePicker.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState } from 'react';
import { Story, Meta } from '@storybook/react/types-6-0';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import { withDesign } from 'storybook-addon-designs';
import { parseTimeZone } from '../../utils/timeHelper';
import DatePicker, { DateRangePicker, DatePickerProps, DateRangePickerProps } from '.';
import './style';
import Docs from './DatePicker.mdx';
Expand All @@ -24,13 +25,13 @@ export default {
} as Meta;

const Template: Story<DatePickerProps> = (args) => {
const [time, setTime] = useState(moment(new Date()));
const [time, setTime] = useState(parseTimeZone(new Date()));
const onChange = (value: Moment | null) => {
value && setTime(value);
};
const { disabledDate } = args;
const handleDisabledDate = (value: Moment) => {
const date = moment(new Date()).add(-1, 'days');
const date = parseTimeZone(new Date()).add(-1, 'days');
return value.isBefore(date);
};
return (
Expand All @@ -46,12 +47,12 @@ Default.args = {
};

function disabledDates(current: Moment) {
return current && current < moment().endOf('day');
return current && current < parseTimeZone().endOf('day');
}

const RangeTemplate: Story<DateRangePickerProps> = (args) => {
const now = new Date();
const [time, setTime] = useState([moment(now), moment(now)]);
const [time, setTime] = useState([parseTimeZone(now), parseTimeZone(now)]);
const onChange = (value: Array<Moment> | null) => {
value && setTime(value);
};
Expand Down
5 changes: 3 additions & 2 deletions src/legacy/date-picker/hook/useDatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import { parseTimeZone } from '../../../utils/timeHelper';
import { DatePickerProps } from '../interface';

const useDatePicker = (props: DatePickerProps) => {
Expand Down Expand Up @@ -39,7 +40,7 @@ const useDatePicker = (props: DatePickerProps) => {
};

const debounceTimeChange = (e: string): void => {
const values = moment(e, props.format);
const values = parseTimeZone(e, props.format);
setLocalValue(values.isValid() ? values : localValue);
};

Expand Down
7 changes: 4 additions & 3 deletions src/legacy/date-picker/hook/useDateRangePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef } from 'react';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import { parseTimeZone } from '../../../utils/timeHelper';
import { DateRangePickerProps } from '../interface';

const useDateRangePicker = (props: DateRangePickerProps) => {
Expand Down Expand Up @@ -38,13 +39,13 @@ const useDateRangePicker = (props: DateRangePickerProps) => {

const handleLeftInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
setLeftInputTimeRange(e.target.value);
const values = moment(e.target.value, props.format);
const values = parseTimeZone(e.target.value, props.format);
debounceInputChange(values, 'left');
};

const handleRightInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
setRightInputTimeRange(e.target.value);
const values = moment(e.target.value, props.format);
const values = parseTimeZone(e.target.value, props.format);
debounceInputChange(values, 'right');
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import { parseTimeZone } from '../../../../../../../../utils/timeHelper';
import RelativeCurrent from './components/RelativeCurrent';
import RelativeBetween from './components/RelativeBetween';
import IncludeToday from './components/IncludeToday';
Expand All @@ -16,30 +17,30 @@ interface DateAttrSelectProps {
function DateAttrSelect(props: DateAttrSelectProps) {
const { attrSelect, attrChange, values, style } = props;
const [time, setTime] = useState<Moment>(
values?.[0] && parseFloat(values?.[0]).toString() !== 'NaN' ? moment(parseInt(values?.[0], 10)) : moment(Date.now())
values?.[0] && parseFloat(values?.[0]).toString() !== 'NaN' ? parseTimeZone(parseInt(values?.[0], 10)) : parseTimeZone(Date.now())
);
const [timeRange, setTimeRange] = useState<Moment[]>(
values.length && values?.[0]?.includes?.('abs')
? [
moment(parseInt(values?.[0].split(':')[1].split(',')[0], 10)),
moment(parseInt(values?.[0].split(':')[1].split(',')[1], 10)),
parseTimeZone(parseInt(values?.[0].split(':')[1].split(',')[0], 10)),
parseTimeZone(parseInt(values?.[0].split(':')[1].split(',')[1], 10)),
]
: [moment(Date.now()), moment(Date.now())]
: [parseTimeZone(Date.now()), parseTimeZone(Date.now())]
);

useEffect(() => {
setTime(
values?.[0] && parseFloat(values?.[0]).toString() !== 'NaN'
? moment(parseInt(values?.[0], 10))
: moment(Date.now())
? parseTimeZone(parseInt(values?.[0], 10))
: parseTimeZone(Date.now())
);
setTimeRange(
values.length && values?.[0]?.includes?.('abs')
? [
moment(parseInt(values?.[0].split(':')[1].split(',')[0], 10)),
moment(parseInt(values?.[0].split(':')[1].split(',')[1], 10)),
parseTimeZone(parseInt(values?.[0].split(':')[1].split(',')[0], 10)),
parseTimeZone(parseInt(values?.[0].split(':')[1].split(',')[1], 10)),
]
: [moment(Date.now()), moment(Date.now())]
: [parseTimeZone(Date.now()), parseTimeZone(Date.now())]
);
}, [values]);

Expand Down Expand Up @@ -75,32 +76,32 @@ function DateAttrSelect(props: DateAttrSelectProps) {
} else if (attrSelect === 'between' || attrSelect === 'not between') {
// 在。。。与。。。之间,值的初始化
attrChange([
`abs:${moment(timeRange?.[0], 'YYYY-MM-DD').startOf('day').valueOf()},${moment(timeRange?.[1], 'YYYY-MM-DD')
`abs:${parseTimeZone(timeRange?.[0], 'YYYY-MM-DD').startOf('day').valueOf()},${parseTimeZone(timeRange?.[1], 'YYYY-MM-DD')
.endOf('day')
.valueOf()}`,
]);
} else {
attrChange([`${moment(Date.now()).valueOf()}`]);
attrChange([`${parseTimeZone(Date.now()).valueOf()}`]);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [attrSelect]);

const changeDate = (value: Date | null) => {
const date = moment(value);
const date = parseTimeZone(value);
date && setTime(date);
attrChange([`${moment(date, 'YYYY-MM-DD').startOf('day').valueOf()}`]);
attrChange([`${parseTimeZone(date, 'YYYY-MM-DD').startOf('day').valueOf()}`]);
};
const relativeDateChange = (v: string) => {
attrChange([v]);
};
const dateRangeChange = (value?: [NullableDate, NullableDate]) => {
if (!value || value.some((item) => !moment(item).isValid())) return;
const dateRange = [moment(value[0]), moment(value[1])];
if (!value || value.some((item) => !parseTimeZone(item).isValid())) return;
const dateRange = [parseTimeZone(value[0]), parseTimeZone(value[1])];
dateRange && setTimeRange(dateRange);
dateRange &&
attrChange([
`abs:${moment(dateRange?.[0], 'YYYY-MM-DD').startOf('day').valueOf()},${moment(dateRange?.[1], 'YYYY-MM-DD')
`abs:${parseTimeZone(dateRange?.[0], 'YYYY-MM-DD').startOf('day').valueOf()},${parseTimeZone(dateRange?.[1], 'YYYY-MM-DD')
.endOf('day')
.valueOf()}`,
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import moment from 'moment';
import { parseTimeZone } from '../../../../../../../utils/timeHelper';
import { listFormat } from '../../../../..';
import { TextObject } from '../../../../../FilterPicker';
import { attributeValue } from '../interfaces';
Expand Down Expand Up @@ -151,34 +151,34 @@ const parseDateValuesToText = (operation: string, value: string[], t: TextObject
if (value[0] === ' ') {
return t.hasValue;
}
return `${t['!=']} ${moment(parseInt(value[0], 10)).format('YYYY-MM-DD')}`;
return `${t['!=']} ${parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD')}`;
}
case '=': {
if (value[0] === ' ') {
return t.noValue;
}
return `${t['=']} ${moment(parseInt(value[0], 10)).format('YYYY-MM-DD')}`;
return `${t['=']} ${parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD')}`;
}
case '>':
// 在 xxx 天之后
return t.somedayAfter(moment(parseInt(value[0], 10)).format('YYYY-MM-DD'));
return t.somedayAfter(parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD'));
case '>=':
// 在 xxx 天之后包括当天
return t.somedayAfterInclude(moment(parseInt(value[0], 10)).format('YYYY-MM-DD'));
return t.somedayAfterInclude(parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD'));
case '<':
// 在 xxx 天之前
return t.somedayAgo(moment(parseInt(value[0], 10)).format('YYYY-MM-DD'));
return t.somedayAgo(parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD'));
// 在 xxx 天之前包括当天
case '<=':
return t.somedayAgoInclude(moment(parseInt(value[0], 10)).format('YYYY-MM-DD'));
return t.somedayAgoInclude(parseTimeZone(parseInt(value[0], 10)).format('YYYY-MM-DD'));
// 判断,在。。。与。。。之间
// 返回字符串 ---- ‘在(date1)与(data2)之间’
case 'between':
if (value[0].includes('abs')) {
const abs = value?.[0].split(':')[1].split(',');
return t.between(
listFormat(
[moment(parseInt(abs[0], 10)).format('YYYY-MM-DD'), moment(parseInt(abs[1], 10)).format('YYYY-MM-DD')],
[parseTimeZone(parseInt(abs[0], 10)).format('YYYY-MM-DD'), parseTimeZone(parseInt(abs[1], 10)).format('YYYY-MM-DD')],
t.code
)
);
Expand All @@ -189,7 +189,7 @@ const parseDateValuesToText = (operation: string, value: string[], t: TextObject
const abs = value?.[0].split(':')[1].split(',');
return t.notBetween(
listFormat(
[moment(parseInt(abs[0], 10)).format('YYYY-MM-DD'), moment(parseInt(abs[1], 10)).format('YYYY-MM-DD')],
[parseTimeZone(parseInt(abs[0], 10)).format('YYYY-MM-DD'), parseTimeZone(parseInt(abs[1], 10)).format('YYYY-MM-DD')],
t.code
)
);
Expand All @@ -204,9 +204,9 @@ const parseDateValuesToText = (operation: string, value: string[], t: TextObject
return parseDateValuesRelativeToText(relativeTime, t);
}
case 'hasValue':
return `${t.hasValue} ${moment(value[0]).format('YYYY-MM-DD')}`;
return `${t.hasValue} ${parseTimeZone(value[0]).format('YYYY-MM-DD')}`;
default:
return moment(value[0]).format('YYYY-MM-DD');
return parseTimeZone(value[0]).format('YYYY-MM-DD');
}
};

Expand Down
7 changes: 4 additions & 3 deletions src/legacy/time-picker/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import classNames from 'classnames';
import { parseTimeZone } from '../../utils/timeHelper';
// import Header from './Header';
import Combobox from './Combobox';
import { PanelProps } from './interface';
Expand All @@ -20,7 +21,7 @@ function toNearestValidTime(time: Moment, hourOptions: number[], minuteOptions:
const hour = hourOptions.slice().sort((a, b) => Math.abs(time.hour() - a) - Math.abs(time.hour() - b))[0];
const minute = minuteOptions.slice().sort((a, b) => Math.abs(time.minute() - a) - Math.abs(time.minute() - b))[0];
const second = secondOptions.slice().sort((a, b) => Math.abs(time.second() - a) - Math.abs(time.second() - b))[0];
return moment(`${hour}:${minute}:${second}`, 'HH:mm:ss');
return parseTimeZone(`${hour}:${minute}:${second}`, 'HH:mm:ss');
}
interface PanelState {
value: Moment;
Expand All @@ -33,7 +34,7 @@ class Panel extends Component<PanelProps, PanelState> {
disabledHours: noop,
disabledMinutes: noop,
disabledSeconds: noop,
defaultOpenValue: moment(),
defaultOpenValue: parseTimeZone() as Moment,
use12Hours: false,
addon: noop,
onKeyDown: noop,
Expand Down
5 changes: 3 additions & 2 deletions src/legacy/time-picker/TimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { Component, ReactNode } from 'react';
import Trigger from 'rc-trigger';
import moment, { Moment } from 'moment';
import { Moment } from 'moment';
import classNames from 'classnames';
import { parseTimeZone } from '../../utils/timeHelper';
import Panel from './Panel';
import placements, { defaultAlign } from './placements';
import { TimePickerProps } from './interface';
Expand Down Expand Up @@ -31,7 +32,7 @@ class Picker extends Component<TimePickerProps, TimePickerState> {
popupClassName: '',
popupStyle: {},
align: defaultAlign,
defaultOpenValue: moment(),
defaultOpenValue: parseTimeZone() as Moment,
allowEmpty: true,
showHour: true,
showMinute: true,
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/time-picker/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface TimePickerProps {
defaultValue?: Moment;
/**
* defaultOpenValue
* @default moment()
* @default parseTimeZone()
*/
defaultOpenValue?: Moment;
defaultOpen: boolean;
Expand Down
10 changes: 5 additions & 5 deletions src/past-time-picker/PastTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import classnames from 'classnames';
import has from 'lodash/has';
import get from 'lodash/get';
import omit from 'lodash/omit';
import { format } from 'date-fns';
import { parseFnsTimeZone } from '../utils/timeHelper'
import Popover from '../popover';
import { InputButton } from '../input';
import { PastTimePickerProps } from './interfaces';
Expand Down Expand Up @@ -115,17 +115,17 @@ const PastTimePicker = (props: PastTimePickerProps) => {
const items = time.split(':');
const times = items[1].split(',').map((str) => parseInt(str, 10));
if (items[0] === 'since') {
const start = format(times[0], 'yyyy/MM/dd');
const start = parseFnsTimeZone(times[0], 'yyyy/MM/dd');
return `${FromText} ${start} ${toTodayText}`;
}
if (items[0] === 'since-lt-today') {
const start = format(times[0], 'yyyy/MM/dd');
const start = parseFnsTimeZone(times[0], 'yyyy/MM/dd');
return `${FromText} ${start} ${toYesterdayText}`;
}

if (items[0] === 'abs') {
const start = format(times[0], 'yyyy/MM/dd');
const end = format(times[1], 'yyyy/MM/dd');
const start = parseFnsTimeZone(times[0], 'yyyy/MM/dd');
const end = parseFnsTimeZone(times[1], 'yyyy/MM/dd');
return `${FromText} ${start} ${ToText} ${end}`;
}
if (items[0] === 'day') {
Expand Down
Loading

0 comments on commit 6f6d503

Please sign in to comment.