fix: fix date format (#686)
* fix: fix date format * fix: fix date format * fix: export date * fix: get current timezone * fix: datetime render * fix: gmt * fix: gmt date * fix: utf offset Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
95e799880c
commit
165ab2b876
@ -37,6 +37,12 @@ export interface ApplicationOptions {
|
||||
plugins?: any[];
|
||||
}
|
||||
|
||||
export const getCurrentTimezone = () => {
|
||||
const timezoneOffset = new Date().getTimezoneOffset() / -60;
|
||||
const timezone = String(timezoneOffset).padStart(2, '0') + ':00';
|
||||
return (timezoneOffset > 0 ? '+' : '-') + timezone;
|
||||
};
|
||||
|
||||
export type PluginCallback = () => Promise<any>;
|
||||
|
||||
export class Application {
|
||||
@ -51,6 +57,7 @@ export class Application {
|
||||
baseURL: process.env.API_BASE_URL,
|
||||
headers: {
|
||||
'X-Hostname': window?.location?.hostname,
|
||||
'X-Timezone': getCurrentTimezone(),
|
||||
},
|
||||
...options.apiClient,
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import { DatePicker as AntdDatePicker } from 'antd';
|
||||
import type {
|
||||
DatePickerProps as AntdDatePickerProps,
|
||||
RangePickerProps as AntdRangePickerProps,
|
||||
RangePickerProps as AntdRangePickerProps
|
||||
} from 'antd/lib/date-picker';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import React from 'react';
|
||||
import { ReadPretty } from './ReadPretty';
|
||||
import { mapDateFormat } from './util';
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { usePrefixCls } from '@formily/antd/lib/__builtins__';
|
||||
import { isArr } from '@formily/shared';
|
||||
import { getDefaultFormat, str2moment } from '@nocobase/utils/client';
|
||||
import type {
|
||||
DatePickerProps as AntdDatePickerProps,
|
||||
RangePickerProps as AntdRangePickerProps
|
||||
@ -7,7 +8,6 @@ import type {
|
||||
import cls from 'classnames';
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { getDefaultFormat, str2moment } from './util';
|
||||
|
||||
type Composed = {
|
||||
DatePicker: React.FC<AntdDatePickerProps>;
|
||||
@ -38,7 +38,7 @@ ReadPretty.DateRangePicker = (props: any) => {
|
||||
if (!m) {
|
||||
return '';
|
||||
}
|
||||
const labels = m.map(m => m.format(format));
|
||||
const labels = m.map((m) => m.format(format));
|
||||
return isArr(labels) ? labels.join('~') : labels;
|
||||
};
|
||||
return (
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { str2moment } from '@nocobase/utils';
|
||||
import moment from 'moment';
|
||||
import { moment2str, str2moment } from '../util';
|
||||
import { moment2str } from '../util';
|
||||
|
||||
describe('str2moment', () => {
|
||||
describe('string value', () => {
|
||||
@ -7,12 +8,12 @@ describe('str2moment', () => {
|
||||
const m = str2moment('2022-06-21T00:00:00.000Z', { gmt: true });
|
||||
expect(m.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-06-21 00:00:00');
|
||||
});
|
||||
|
||||
|
||||
test('local date', async () => {
|
||||
const m = str2moment('2022-06-21T00:00:00.000Z');
|
||||
expect(m.toISOString()).toBe('2022-06-21T00:00:00.000Z');
|
||||
});
|
||||
|
||||
|
||||
test('value is null', async () => {
|
||||
const m = str2moment(null);
|
||||
expect(m).toBeNull();
|
||||
@ -31,7 +32,7 @@ describe('str2moment', () => {
|
||||
expect(m.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-06-21 00:00:00');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('local date', async () => {
|
||||
const arr = str2moment(['2022-06-21T00:00:00.000Z', '2022-06-21T00:00:00.000Z']);
|
||||
for (const m of arr) {
|
||||
|
@ -1,18 +1,6 @@
|
||||
import type { DatePickerProps } from 'antd/lib/date-picker';
|
||||
import { getDefaultFormat, str2moment, toGmt, toLocal } from '@nocobase/utils/client';
|
||||
import moment from 'moment';
|
||||
|
||||
const toGmt = (value: moment.Moment | moment.Moment[]) => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => `${val.format('YYYY-MM-DD')}T${val.format('HH:mm:ss.SSS')}Z`);
|
||||
}
|
||||
if (moment.isMoment(value)) {
|
||||
return `${value.format('YYYY-MM-DD')}T${value.format('HH:mm:ss.SSS')}Z`;
|
||||
}
|
||||
};
|
||||
|
||||
const toStringByPicker = (value, picker) => {
|
||||
if (picker === 'year') {
|
||||
return value.format('YYYY') + '-01-01T00:00:00.000Z';
|
||||
@ -41,45 +29,6 @@ const toGmtByPicker = (value: moment.Moment | moment.Moment[], picker?: any) =>
|
||||
}
|
||||
};
|
||||
|
||||
const toLocal = (value: moment.Moment | moment.Moment[]) => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => val.toISOString());
|
||||
}
|
||||
if (moment.isMoment(value)) {
|
||||
return value.toISOString();
|
||||
}
|
||||
};
|
||||
|
||||
export interface Str2momentOptions {
|
||||
gmt?: boolean;
|
||||
picker?: 'year' | 'month' | 'week' | 'quarter';
|
||||
}
|
||||
|
||||
const toMoment = (val: any, options?: Str2momentOptions) => {
|
||||
if (moment.isMoment(val)) {
|
||||
return val;
|
||||
}
|
||||
const { gmt, picker } = options;
|
||||
if (gmt || picker) {
|
||||
val = val.replace('T', ' ').replace('Z', '');
|
||||
return moment(val);
|
||||
}
|
||||
return moment(val);
|
||||
};
|
||||
|
||||
export const str2moment = (value?: string | string[], options: Str2momentOptions = {}): any => {
|
||||
return Array.isArray(value)
|
||||
? value.map((val) => {
|
||||
return toMoment(val, options);
|
||||
})
|
||||
: value
|
||||
? toMoment(value, options)
|
||||
: value;
|
||||
};
|
||||
|
||||
export interface Moment2strOptions {
|
||||
showTime?: boolean;
|
||||
gmt?: boolean;
|
||||
@ -97,28 +46,6 @@ export const moment2str = (value?: moment.Moment | moment.Moment[], options: Mom
|
||||
return toGmtByPicker(value, picker);
|
||||
};
|
||||
|
||||
export const getDefaultFormat = (props: DatePickerProps & { dateFormat: string; timeFormat: string }) => {
|
||||
if (props.format) {
|
||||
return props.format;
|
||||
}
|
||||
if (props.dateFormat) {
|
||||
if (props['showTime']) {
|
||||
return `${props.dateFormat} ${props.timeFormat || 'HH:mm:ss'}`;
|
||||
}
|
||||
return props.dateFormat;
|
||||
}
|
||||
if (props['picker'] === 'month') {
|
||||
return 'YYYY-MM';
|
||||
} else if (props['picker'] === 'quarter') {
|
||||
return 'YYYY-\\QQ';
|
||||
} else if (props['picker'] === 'year') {
|
||||
return 'YYYY';
|
||||
} else if (props['picker'] === 'week') {
|
||||
return 'YYYY-wo';
|
||||
}
|
||||
return props['showTime'] ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
|
||||
};
|
||||
|
||||
export const mapDateFormat = function () {
|
||||
return (props: any) => {
|
||||
const format = getDefaultFormat(props) as any;
|
||||
|
@ -14,5 +14,9 @@
|
||||
"deepmerge": "^4.2.2",
|
||||
"flat-to-nested": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"moment": "2.x",
|
||||
"rc-input-number": "7.x"
|
||||
},
|
||||
"gitHead": "7e9556e489007577fc0ed89063b3a9ce2f9aae53"
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from './date';
|
||||
export * from './merge';
|
||||
export * from './number';
|
||||
export * from './registry';
|
||||
|
78
packages/core/utils/src/date.ts
Normal file
78
packages/core/utils/src/date.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import moment from 'moment';
|
||||
|
||||
export interface Str2momentOptions {
|
||||
gmt?: boolean;
|
||||
picker?: 'year' | 'month' | 'week' | 'quarter';
|
||||
utcOffset?: any;
|
||||
}
|
||||
|
||||
export const getDefaultFormat = (props: any) => {
|
||||
if (props.format) {
|
||||
return props.format;
|
||||
}
|
||||
if (props.dateFormat) {
|
||||
if (props['showTime']) {
|
||||
return `${props.dateFormat} ${props.timeFormat || 'HH:mm:ss'}`;
|
||||
}
|
||||
return props.dateFormat;
|
||||
}
|
||||
if (props['picker'] === 'month') {
|
||||
return 'YYYY-MM';
|
||||
} else if (props['picker'] === 'quarter') {
|
||||
return 'YYYY-\\QQ';
|
||||
} else if (props['picker'] === 'year') {
|
||||
return 'YYYY';
|
||||
} else if (props['picker'] === 'week') {
|
||||
return 'YYYY-wo';
|
||||
}
|
||||
return props['showTime'] ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
|
||||
};
|
||||
|
||||
export const toGmt = (value: moment.Moment | moment.Moment[]) => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => `${val.format('YYYY-MM-DD')}T${val.format('HH:mm:ss.SSS')}Z`);
|
||||
}
|
||||
if (moment.isMoment(value)) {
|
||||
return `${value.format('YYYY-MM-DD')}T${value.format('HH:mm:ss.SSS')}Z`;
|
||||
}
|
||||
};
|
||||
|
||||
export const toLocal = (value: moment.Moment | moment.Moment[]) => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => val.toISOString());
|
||||
}
|
||||
if (moment.isMoment(value)) {
|
||||
return value.toISOString();
|
||||
}
|
||||
};
|
||||
|
||||
const toMoment = (val: any, options?: Str2momentOptions) => {
|
||||
if (!val) {
|
||||
return;
|
||||
}
|
||||
const offset = options.utcOffset || -1 * new Date().getTimezoneOffset();
|
||||
if (moment.isMoment(val)) {
|
||||
return val.utcOffset(offset);
|
||||
}
|
||||
const { gmt, picker } = options;
|
||||
if (gmt || picker) {
|
||||
return moment(val).utcOffset(0);
|
||||
}
|
||||
return moment(val).utcOffset(offset);
|
||||
};
|
||||
|
||||
export const str2moment = (value?: string | string[], options: Str2momentOptions = {}): any => {
|
||||
return Array.isArray(value)
|
||||
? value.map((val) => {
|
||||
return toMoment(val, options);
|
||||
})
|
||||
: value
|
||||
? toMoment(value, options)
|
||||
: value;
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
export * from './date';
|
||||
export * from './merge';
|
||||
export * from './mixin';
|
||||
export * from './mixin/AsyncEmitter';
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from './date';
|
||||
export * from './merge';
|
||||
export * from './mixin';
|
||||
export * from './mixin/AsyncEmitter';
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { toFixedByStep } from '@nocobase/utils';
|
||||
import moment from 'moment';
|
||||
import { getDefaultFormat, str2moment } from '@nocobase/utils';
|
||||
|
||||
export async function _(field, row, ctx, column?: any) {
|
||||
if (column?.dataIndex.length > 1) {
|
||||
@ -34,7 +33,14 @@ export async function _(field, row, ctx, column?: any) {
|
||||
|
||||
export async function datetime(field, row, ctx) {
|
||||
const value = row.get(field.name);
|
||||
return moment(value).format(field.showTime ? `${field.dateFormat} ${field.timeFormat}` : field.dateFormat);
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const utcOffset = ctx.get('X-Timezone');
|
||||
const props = field.options?.uiSchema?.['x-component-props'] ?? {};
|
||||
const format = getDefaultFormat(props);
|
||||
const m = str2moment(value, { ...props, utcOffset });
|
||||
return m ? m.format(format) : '';
|
||||
}
|
||||
|
||||
export async function percent(field, row, ctx) {
|
||||
|
Loading…
Reference in New Issue
Block a user