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

切换至美国时区后事件日期输入框显示日期异常求助

日期时区偏移问题修复方案

问题

切换本地时区为美国时区时,事件日期输入框(type="date")选中03-14-2024,却显示03-13-2024,其他时区下也可能出现类似日期偏移问题。运行环境:WordPress 6.4.3、moment.js、PHP 8.0.30。需求:无论本地时区如何调整,输入框显示日期与用户选中日期完全一致。

原因

type="date"输入框的value为ISO纯日期格式(YYYY-MM-DD),使用new Date(value)或直接moment(value)解析时,浏览器会默认将其视为UTC时区的0点,再转换为本地时区时间。例如美国时区(UTC-5至UTC-8)下,UTC的03-14-2024T00:00:00转换为本地时间就是03-13-2024的下午/晚上,格式化后就会显示前一天的日期。

修复方案

核心思路:将type="date"的纯日期值直接解析为本地时区的日期,跳过UTC转换逻辑;同时统一所有日期处理的时区解析规则。

修改后的JavaScript代码

// Script for date formatting
function formatDate(inputId) {
    const input = document.getElementById(inputId);
    const value = input.value;
    if (!value) return;

    // 针对type="date"的输入,直接按本地日期解析,避免UTC转换
    const dateFormat = input.getAttribute("data-date-format");
    let formattedDate;
    if (input.type === 'date') {
        formattedDate = moment(value, 'YYYY-MM-DD').format(dateFormat);
    } else {
        // 针对datetime-local类型,明确用本地时区解析
        formattedDate = moment(value).local().format(dateFormat);
    }

    input.setAttribute("data-date", formattedDate);
}

// Trigger change event to initialize the custom display format
const pickup_date_validate = document.getElementById('pickup-date-validate');
if (pickup_date_validate) {
    pickup_date_validate.dispatchEvent(new Event('change'));
}
const return_date_validate = document.getElementById('return-date-validate');
if (return_date_validate) {
    return_date_validate.dispatchEvent(new Event('change'));
}
const event_date_validate = document.getElementById('event-date-validate');
if (event_date_validate) {
    event_date_validate.dispatchEvent(new Event('change'));
}

jQuery(document).ready(function ($) {
    // Initialize selectedPickUpDate and selectedReturnDate variables
    let selectedPickUpDate;
    let selectedReturnDate;
    
    // Function to format date using moment.js
    function formatMomentDate(date, format) {
        return date ? date.format(format) : "";
    }
    
    // Pickup Date
    let pickUpDateSelect = document.getElementById("pickup-date-validate");
    if (pickUpDateSelect !== null) {
        // Set the minimum value for the input to the current date and time
        const pickUpNow = moment().local();
        pickUpDateSelect.min = formatMomentDate(pickUpNow, "YYYY-MM-DDTHH:mm");

        // Event listener for pickup date selection
        $(pickUpDateSelect).on("change input", function () {
            // 明确按本地时区解析datetime-local的值
            selectedPickUpDate = moment($(this).val()).local();

            // Condition 1: When Pickup date is selected, set Return date minimum value
            let returnMinDate = moment(selectedPickUpDate).add(1, 'days');
            ReturnDateSelect.min = formatMomentDate(returnMinDate, "YYYY-MM-DDTHH:mm");

            // Update data-date attribute and format
            this.setAttribute("data-date", selectedPickUpDate ? selectedPickUpDate.format("MM-DD-YYYY HH:mm") : '');
            this.setAttribute("data-date-format", "MM-DD-YYYY HH:mm");

            // Update Event Date minimum value to allow selecting the pickup date
            EventDateSelect.min = formatMomentDate(selectedPickUpDate, "YYYY-MM-DD");
        });
    }

    // Return Date
    let ReturnDateSelect = document.getElementById("return-date-validate");
    if (ReturnDateSelect !== null) {
        // Event listener for return date selection
        $(ReturnDateSelect).on("change input", function () {
            // 明确按本地时区解析datetime-local的值
            selectedReturnDate = moment($(this).val()).local();

            // Adjust Return date minimum value to prevent selecting the same date as the pickup date
            let adjustedReturnMinDate = moment(selectedPickUpDate).add(1, 'days');
            ReturnDateSelect.min = formatMomentDate(adjustedReturnMinDate, "YYYY-MM-DDTHH:mm");

            // Condition 2: When Return date is selected, set Event date minimum and maximum values
            let eventMinDate = moment(selectedPickUpDate);
            let eventMaxDate = moment(selectedReturnDate);
            EventDateSelect.min = formatMomentDate(eventMinDate, "YYYY-MM-DD");
            EventDateSelect.max = formatMomentDate(eventMaxDate, "YYYY-MM-DD");

            // Update data-date attribute and format
            this.setAttribute("data-date", selectedReturnDate ? selectedReturnDate.format("MM-DD-YYYY HH:mm") : '');
            this.setAttribute("data-date-format", "MM-DD-YYYY HH:mm");
        });
    }

    // Event Date
    let EventDateSelect = document.getElementById("event-date-validate");
    if (EventDateSelect !== null) {
        // Event listener for event date selection
        $(EventDateSelect).on("change input", function () {
            // 直接按本地日期解析,避免UTC转换
            const selectedEventDate = moment($(this).val(), 'YYYY-MM-DD');

            // Disable pickup date and dates after return date in the event date selection
            if (selectedReturnDate && selectedEventDate.isAfter(selectedReturnDate, 'day')) {
                $(this).val(""); // Clear event date
            }
            // 同步更新data-date属性
            const dateFormat = this.getAttribute("data-date-format");
            const formattedDate = selectedEventDate.format(dateFormat);
            this.setAttribute("data-date", formattedDate);
        });
    }
});

关键修改点

  • formatDate函数:针对type="date"的输入,使用moment(value, 'YYYY-MM-DD')直接解析为本地日期,跳过UTC转换;datetime-local类型用.local()明确指定本地时区解析。
  • 事件监听中的日期解析:所有datetime-local值解析时添加.local(),确保基于本地时区处理;事件日期的解析同样直接按纯本地日期处理。
  • 日期比较逻辑:事件日期与返回日期比较时,添加'day'参数,确保按日期(而非时间)维度判断是否超出范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:23:15