通过 API,我读取我的 Outlook 日历并将其显示在 FullCalendar 库的日历中。
我的问题是在读取具有持续时间的事件时出现的,在我的网络日历中显示时在 Outlook 中创建的所有事件都会从开始和结束时间减去两个小时,我附上示例图片:
展望事件
翻译:2024 年 6 月 5 日星期三下午 1:30 开始至下午 3:00
我的日历上的活动
翻译:开始:06/05/2024 11:30 a.m. |结束于 06/05/2024 13:00 pm
两者都发生在 5 日,但 Outlook 中的原始事件于下午 1:30 开始。并于下午 3:00 结束我的日历显示好像是从上午 11:00 开始,到下午 1:30 结束,相隔两个小时。
在我的代码中,我在控制台中添加了一条消息,以查看通过 API 读取的时间是如何到达的,它以以下格式到达:Wed Jun 05 2024 11:30:00 GMT+0200(中欧夏令时间)
所以我认为从外观来看它到达的是错误的,但我很惊讶,因为我住的地方 GTM 是正确的。
这是获取事件的部分:
//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();
}
非常感谢!
编辑:虽然@derpirscher的解决方案工作得很好,但我添加了同事向我推荐的另一种方法,它也有效
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 => {
// Convertir las fechas y horas a objetos de fecha considerando la zona horaria
const start = new Date(event.start.dateTime);
const end = new Date(event.end.dateTime);
// Ajustar la hora para reflejar la zona horaria local
const timeZoneOffset = start.getTimezoneOffset() * 60000; // Convertir minutos a milisegundos
const localStart = new Date(start.getTime() - timeZoneOffset);
const localEnd = new Date(end.getTime() - timeZoneOffset);
return {
title: event.subject,
start: localStart.toISOString(), // Convertir a cadena ISO para asegurar la representación correcta de la fecha y hora
end: localEnd.toISOString(),
allDay: event.isAllDay
};
});
return events;
}
您忽略了从 API 获取的时区信息。您的回复包含以下格式的时间戳
{
dateTime: "2024-06-12T09:30:00.0000000",
timeZone: "UTC"
}
但是在你的代码中,当读取 API 响应时,你只考虑
...
start: event.start.dateTime,
end: event.end.dateTime,
...
并忽略
event.start.timeZone
信息。
因此,在你的过程中的某个地方你可能会做类似的事情
new Date(start)
将时间字符串转换为
Date
对象。但由于时间字符串不包含任何有关时区的信息,因此它被认为是“本地时间”(即在您的情况下是 CEST,比 UTC 早 2 小时)。
Ie "2024-06-12T09:30:00.0000000"
中的
UTC
与 "2024-06-12T11:30:00.0000000"
中的 CEST
是同一时间点。但是,当您在以 CEST 运行的计算机中执行 new Date("2024-06-12T09:30:00.0000000")
操作时,它将以 CEST 解释此时间字符串(因为它没有任何其他信息),从而导致时间戳发生 2 小时的偏移。因此,在将字符串转换为 Date
时,您必须考虑这些字符串所指的正确时区。一个非常简单的方法可能如下
检查 Outlook API 是否始终 提供 UTC 时区的时间戳。如果是,只需在时间戳字符串中添加 Z
即可。这是日期解析的最简单标记,时间戳将被视为 UTC 时间戳。 IE
new Date("2024-06-12T09:30:00.0000000")
会给你9:30 CEST
但是new Date("2024-06-12T09:30:00.0000000Z")
会给你9:30 UTC
,这与11:30 CEST
相同如果 Outlook API 还返回不同的时区,您必须以某种方式将该信息放入时间戳字符串中。但由于我不知道
timeZone
可以以什么格式交付,因此很难提供帮助......