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

通过API读取Outlook日历事件时的时间偏移问题求助

问题:Outlook日历事件在FullCalendar中显示时间偏移2小时

问题现象

Outlook中创建的带时长事件(如2024年6月5日13:30-15:00),通过Microsoft Graph API获取后,在FullCalendar网页日历中显示为11:30-13:00,整体时间被减去2小时。控制台打印的API返回时间格式为:Wed Jun 05 2024 11:30:00 GMT+0200 (Central European Summer Time),而本地时区正是GMT+0200。

代码现状

获取事件的原代码

//EVENTS
async function getCalendarEvents(accessToken) {
    const response = await fetch('https://graph.microsoft.com/v1.0/me/events', {
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    });

    if (!response.ok) {
        const errorText = await response.text();
        console.error(`Error al obtener los eventos del calendario: ${response.status} ${response.statusText}`, errorText);
        throw new Error('Error al obtener los eventos del calendario');
    }

    const data = await response.json();
    return data.value.map(event => ({
        title: event.subject,
        start: event.start.dateTime,
        end: event.end.dateTime,
        allDay: event.isAllDay
    }));
}

渲染日历的代码

function renderCalendar(events) {
    const calendarEl = document.getElementById('calendar');
    const calendar = new FullCalendar.Calendar(calendarEl, {
        headerToolbar: {
            left: 'prev,next today',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        buttonText: {
            today: 'Hoy',
            month: 'Mes',
            week: 'Semana',
            day: 'Día',
            list: 'Lista'
        },
        initialView: 'dayGridMonth',
        locale: 'es',
        events: events,
        eventClick: function(info) {
                       
            // Get the event properties
            const event = info.event;
            const title = event.title;
            const start = event.start;
            const end = event.end;
            const allDay = event.allDay;
                       
            const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
                       
            const startFormatted = start.toLocaleString('es-ES', { timeZone: timeZone });
            const endFormatted = end ? end.toLocaleString('es-ES', { timeZone: timeZone }) : 'Evento de todo el día';
                       
            // Create the event information string
            let content = `<h2>${title}</h2>`;
            if (!allDay) {
                content += `<p><strong>Inicio:</strong> ${startFormatted}</p>`;
                content += `<p><strong>Fin:</strong> ${endFormatted}</p>`;
            } else {
                content += `<p><strong>Evento de todo el día</strong></p>`;
            }

            // Show SweetAlert2 popup with event information
            Swal.fire({
                title: 'Información del Evento',
                html: content,
                icon: 'info'
            });
                
            console.log(info.event);
            console.log(title);
            console.log(start);
            console.log(end);
            console.log(allDay);
        }
    });
    calendar.render();
}

问题原因

Microsoft Graph API默认返回的dateTime字段是UTC时间,即使字符串中包含时区标识(如GMT+0200),FullCalendar在解析时仍会将其视为UTC时间再转换一次本地时区,导致重复偏移,最终显示时间比实际晚2小时。

解决方案

方案1:让Graph API直接返回本地时区时间(@derpirscher方案)

在请求Graph API时添加Prefer头指定本地时区,API会直接返回对应时区的时间,无需额外转换:

async function getCalendarEvents(accessToken) {
    const response = await fetch('https://graph.microsoft.com/v1.0/me/events', {
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            // 指定本地时区,示例为中欧夏令时,可替换为实际时区ID(如"Europe/Paris")
            'Prefer': 'outlook.timezone="Central European Summer Time"'
        }
    });

    if (!response.ok) {
        const errorText = await response.text();
        console.error(`Error al obtener los eventos del calendario: ${response.status} ${response.statusText}`, errorText);
        throw new Error('Error al obtener los eventos del calendario');
    }

    const data = await response.json();
    return data.value.map(event => ({
        title: event.subject,
        start: event.start.dateTime,
        end: event.end.dateTime,
        allDay: event.isAllDay
    }));
}

方案2:手动调整时区偏移(同事推荐方案)

通过JavaScript手动将API返回的UTC时间转换为本地时间,再传给FullCalendar:

async function getCalendarEvents_Alt(accessToken) {
    const response = await fetch('https://graph.microsoft.com/v1.0/me/events', {
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    });
    if (!response.ok) {
        const errorText = await response.text();
        console.error(`Error al obtener los eventos del calendario: ${response.status} ${response.statusText}`, errorText);
        throw new Error('Error al obtener los eventos del calendario');
    }

    const data = await response.json();

    const events = data.value.map(event => {
        // 将API返回的时间字符串转为Date对象
        const start = new Date(event.start.dateTime);
        const end = new Date(event.end.dateTime);

        // 计算本地时区偏移(分钟转毫秒),调整为本地时间
        const timeZoneOffset = start.getTimezoneOffset() * 60000;
        const localStart = new Date(start.getTime() - timeZoneOffset);
        const localEnd = new Date(end.getTime() - timeZoneOffset);

        return {
            title: event.subject,
            start: localStart.toISOString(), // 转为ISO格式字符串确保正确解析
            end: localEnd.toISOString(),
            allDay: event.isAllDay
        };
    });

    return events;
}

内容的提问来源于stack exchange,提问作者Hugo Jiménez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:43:10