MUI Datepicker:在 Azure 上选择一天前的日期

问题描述 投票:0回答:1

我创建了一个基于 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 上的一个问题,向我建议这可能不是我的问题的原因。

有什么想法吗?

javascript reactjs material-ui azure-web-app-service formik
1个回答
0
投票

好的,解决了。这个问题与本地用户电脑和服务器之间的时区不同有关 - 这很烦人,因为时间在日期选择器中是无关紧要的......

每当选择日期时,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;
///
© www.soinside.com 2019 - 2024. All rights reserved.