Google Calendar API时区问题:事件时间存为UTC而非布鲁塞尔时区
我正在开发一款带API的应用,可通过该API在Google Calendar中创建事件。目前遇到的问题是:事件日期虽能成功添加,但未使用布鲁塞尔时区,而是以UTC时区存储。例如,我想在本地时间8:45创建事件,日历中却显示为6:45。
当前代码如下:
var reservation = new Event { Summary = GenerateReservationSummary(reservationInput, selectedCares), Start = new EventDateTime { DateTimeDateTimeOffset = reservationInput.ReservationDate, TimeZone = TimeZone // string set as "Europe/Brussels" }, End = new EventDateTime { DateTimeDateTimeOffset = GetEndDateTime(reservationInput.ReservationDate, selectedCares), TimeZone = TimeZone }, Reminders = null // No reminders };
调试时已确认ReservationDate确实设置为8:45,且DateTimeKind为Local。我尝试了以下多种方法,但均无效:
new DateTimeOffset(date, TimeSpan.FromHours(2)) new DateTimeOffset(date, TimeZoneInfo.Local.GetUtcOffset(date))
请问我忽略了什么?此外,我使用Angular前端应用提交表单至API,前端组件中日期正确,但API请求payload里却以UTC格式发送。应优先修复前端还是后端?
后端代码核心问题:Google Calendar API的
EventDateTime对象中,若同时设置DateTimeDateTimeOffset(带时区偏移的时间)和TimeZone字段,API会优先采用DateTimeDateTimeOffset的UTC偏移,直接忽略TimeZone参数。你需要二选一配置:要么用本地DateTime + TimeZone,要么用正确偏移的DateTimeOffset。修正代码示例(二选一即可):
方案1:本地DateTime配合时区var brusselsTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Brussels"); var localBrusselsStartTime = TimeZoneInfo.ConvertTime(reservationInput.ReservationDate, brusselsTimeZone); var localBrusselsEndTime = TimeZoneInfo.ConvertTime(GetEndDateTime(reservationInput.ReservationDate, selectedCares), brusselsTimeZone); var reservation = new Event { Summary = GenerateReservationSummary(reservationInput, selectedCares), Start = new EventDateTime { DateTime = localBrusselsStartTime, // 传递不带偏移的本地时间 TimeZone = "Europe/Brussels" }, End = new EventDateTime { DateTime = localBrusselsEndTime, TimeZone = "Europe/Brussels" }, Reminders = null };方案2:确保DateTimeOffset的偏移正确
var brusselsTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Brussels"); var brusselsOffset = brusselsTimeZone.GetUtcOffset(reservationInput.ReservationDate); var startOffset = new DateTimeOffset(reservationInput.ReservationDate, brusselsOffset); var endOffset = new DateTimeOffset(GetEndDateTime(reservationInput.ReservationDate, selectedCares), brusselsOffset); var reservation = new Event { Summary = GenerateReservationSummary(reservationInput, selectedCares), Start = new EventDateTime { DateTimeDateTimeOffset = startOffset, // 确保偏移为布鲁塞尔时区的正确值 // 不要设置TimeZone字段,避免冲突 }, End = new EventDateTime { DateTimeDateTimeOffset = endOffset, }, Reminders = null };前后端修复优先级:优先修复前端。前端提交UTC格式日期的本质是丢失了「用户选择的是布鲁塞尔本地时间」的核心意图——用户在前端选8:45布鲁塞尔时间,前端应明确传递该时区的时间信息,而非默认转成UTC。后端可做兼容处理,但前端是问题源头,修复后能避免后续类似时区歧义问题。
前端修复思路:在Angular中,不要直接将
Date对象转成JSON(默认会转UTC),而是传递带时区偏移的ISO 8601字符串(如2024-05-20T08:45:00+02:00),或者拆分传递日期时间字符串与时区标识(如{"dateTime": "2024-05-20T08:45:00", "timeZone": "Europe/Brussels"}),让后端能准确解析用户的本地时间选择。
内容的提问来源于stack exchange,提问作者Scryper

