You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI X日期选择器在Azure上选中日期差一天问题求助

问题:Azure部署后自定义日期选择器传递日期提前一天

我基于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"。

我已尝试将Linux版Azure应用服务器的时区通过AzureApplication Setting配置为TZ=Europe/London(与本地PC时区一致),但问题未解决。也了解过JavaScript date对象导致的类似问题,但本地运行正常仅Azure出问题,因此怀疑并非该原因。


解决思路

1. 统一日期传递格式,规避Date对象序列化时区问题

问题本质是JSON序列化Date对象时会强制转为UTC时间:你选中的英国夏令时(GMT+1)8月5日0点,转成UTC就是8月4日23点,父组件直接序列化Date对象就会出现偏差。

修改handleDateChange,将Date对象转为YYYY-MM-DD格式的字符串传递,彻底消除时区影响:

import { format } from 'date-fns'; // 引入date-fns的format方法

const handleDateChange = (date) => {
  if (date) {
    // 转为纯日期字符串,不含时区信息
    const dateStr = format(date, 'yyyy-MM-dd');
    helpers.setValue(dateStr);
  } else {
    helpers.setValue(null);
  }
};

后续父组件拿到的是"2023-08-05"这类字符串,无需处理时区转换。

2. 检查Formik表单提交的序列化逻辑

如果父组件直接用JSON.stringify序列化Formik的values提交,必须手动处理日期字段:

// 示例:在Formik的onSubmit中处理日期
const handleSubmit = (values) => {
  const processedValues = {
    ...values,
    event_date: values.event_date ? format(values.event_date, 'yyyy-MM-dd') : null
  };
  // 提交处理后的processedValues
};

确保日期字段以字符串格式传递,而非原始Date对象。

3. 修正组件的value解析逻辑

当前代码中field.value可能存在字符串/Date对象混合的情况,统一解析为Date对象避免渲染异常:

value={field.value 
  ? (typeof field.value === 'string' ? parseISO(field.value) : field.value) 
  : null
}

4. 针对SSR场景检查服务器端时区

如果你的应用是服务器端渲染(比如Next.js部署在Azure),服务器端渲染时的时区可能影响日期初始化。可以在SSR环节强制将日期转为指定时区的格式,或者确保前端初始化时用浏览器时区解析日期。


内容的提问来源于stack exchange,提问作者Jess

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:36:02