我创建了一个基于 Material UI 和 Formik 的自定义日期选择器组件,它将日期值传递给父表单组件,如下所示:
import React from 'react';
import { useField } from 'formik';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import enGB from 'date-fns/locale/en-GB';
import { parseISO } from 'date-fns';
const CustomDateField = ({ name, label, error, helperText, ...props }) => {
const [field, meta, helpers] = useField(name);
const locale = enGB;
const handleDateChange = (date) => {
console.log('date before changes',date)
//this if/else logic is redundant as MUI always passes the data as a date, not a string
if (typeof date === 'string') {
const parsedDate = parseISO(date);
console.log('parsedDate',parsedDate)
helpers.setValue(parsedDate);
} else {
helpers.setValue(date);
console.log('setValueDate',date)
}
};
return (
<div className="pb-4">
<LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={locale}>
<DatePicker
{...field}
{...props}
name={name}
label={label}
value={field.value || null}
onChange={handleDateChange}
sx={{
width: '100%',
}}
slotProps={{
textField: {
variant: 'outlined',
error: Boolean(meta.touched && meta.error), //error handling
helperText: meta.touched && meta.error ? meta.error : helperText,
},
}} //error handling
/>
</LocalizationProvider>
</div>
);
};
export default CustomDateField;
在我的开发环境中本地运行,日期选择器组件中选择的日期是传递给父组件的日期值。但是,在 Azure 应用程序服务上运行此命令时,传递给父组件的日期比组件中选择的日期早一天。
我已经完成了一些日志记录,例如,当我选择日期(英国日期格式)
05/08/2023
时,标题为'date before changes'
的控制台日志的输出是:
Date Sat Aug 05 2023 00:00:00 GMT+0100 (British Summer Time)
但是,按照传递给父组件的时间,该日期是前一天:
"event_date":"2023-08-04T23:00:00.000Z"
.
我在 S.O. 上做了一些搜索。并发现了与时区潜在相关的问题。我尝试使用 Azure
Application Setting
配置将我的(基于 Linux 的)Azure 应用服务器的时区更改为英国时间 TZ=Europe/London
,我相信这与我本地 PC 的时区 (UTC+00:00) Dublin, Edinburgh, Lisbon, London
和(+1 小时)相匹配夏令时差已启用。这并没有解决问题。
我还发现了一些关于 JavaScript date
对象的帖子(例如
link)导致我遇到的相同症状,但虽然该症状相似,但事实上,当我的代码在我的开发人员本地运行时,我没有问题环境,但这是 Azure 上的一个问题,向我建议这可能不是我的问题的原因。
有什么想法吗?
好的,解决了。这个问题与本地用户电脑和服务器之间的时区不同有关 - 这很烦人,因为时间在日期选择器中是无关紧要的......
每当选择日期时,MUI 日期选择器默认时间为 00:00:00。就我而言,在用户的 PC 上,它被设置为 00:00:00 GMT+1,但是服务器(某个地方,我不确定在哪里)设置为 GMT/UTC,因此当日期传递到后端和数据库,减去了1个小时。从 00:00:00 减去 1 小时将日期移至前一天。
可能有更优雅的方法可以在服务器时区级别解决此问题,但由于我的所有用户都位于英国,我只是对其进行编码以设置默认时间上午 5 点,因此减去 1 小时永远不会导致日期更改。
任何感兴趣的人的新代码:
import React from 'react';
import { useField } from 'formik';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import enGB from 'date-fns/locale/en-GB';
import { setHours, setMinutes } from 'date-fns';
const CustomDateField = ({ name, label, error, helperText, ...props }) => {
const [field, meta, helpers] = useField(name);
const locale = enGB;
const handleDateChange = (date) => {
// Set the time to 5am, otherwise it defaults the time to 00:00:00, meaning during BST it will subtract 1 hour, which will result in a date change too.
const dateWithDefaultTime = setMinutes(setHours(date, 5), 0);
helpers.setValue(dateWithDefaultTime);
};
return (
<div className="pb-4">
<LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={locale}>
<DatePicker
{...field}
{...props}
name={name}
label={label}
value={field.value || null}
onChange={handleDateChange}
sx={{
width: '100%',
}}
slotProps={{
textField: {
variant: 'outlined',
error: Boolean(meta.touched && meta.error),
helperText: meta.touched && meta.error ? meta.error : helperText,
},
}}
/>
</LocalizationProvider>
</div>
);
};
export default CustomDateField;
///