通过Google Calendar API添加事件时时间始终偏移-3小时的问题
Google Calendar API PHP SDK 同步时间偏移3小时问题排查
我使用Google API PHP SDK实现Google Calendar集成,将系统内事件同步至日历。功能已基本实现,但所有同步的事件在日历中显示的时间始终比预期晚3小时。我的日历时区设置为圣保罗(GMT-3),尝试了多种传参方式均无法解决问题:
- 方式1:传递带+00:00时区的日期时间
Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-30T00:00:00+00:00 ) [end] => Array ( [dateTime] => 2023-03-31T23:59:59+00:00 ) )
- 方式2:传递带-03:00时区的日期时间
Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-29T21:00:00-03:00 ) [end] => Array ( [dateTime] => 2023-03-31T20:59:59-03:00 ) )
- 方式3:单独传递时区(日期时间为+00:00)
Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-30T00:00:00+00:00 ) [end] => Array ( [dateTime] => 2023-03-31T23:59:59+00:00 ) )
- 方式4:同时传递带-03:00时区的日期时间和America/Sao_Paulo时区参数
Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-29T21:00:00-03:00 [timeZone] => America/Sao_Paulo ) [end] => Array ( [dateTime] => 2023-03-31T20:59:59-03:00 [timeZone] => America/Sao_Paulo ) )
无论采用哪种方式,日历中显示的事件时间始终为:
2023年3月29日 晚上9:00 – 2023年3月31日 晚上8:59
问题原因与解决方案
核心问题是你传递的时间本身就对应日历显示的结果,而非API自动转换错误:
- 你想显示圣保罗时间3月30日00:00,但第一种方式传递的是UTC时间3月30日00:00,对应圣保罗时间就是3月29日21:00;
- 第二种方式直接传递了圣保罗时间3月29日21:00,日历自然显示该时间;
- 第三、四种方式同理,传递的时间值本身就对应显示的结果。
正确传参方式
选择以下任意一种即可:
直接传递圣保罗时区的本地时间(带-03:00偏移)
若要显示圣保罗时间3月30日00:00至3月31日23:59,直接传递:Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-30T00:00:00-03:00 ) [end] => Array ( [dateTime] => 2023-03-31T23:59:59-03:00 ) )传递UTC时间+指定事件时区
先将圣保罗时间转换为UTC(3月30日00:00对应UTC的3月30日03:00),再指定时区参数:Array ( [summary] => test [location] => test [description] => test [start] => Array ( [dateTime] => 2023-03-30T03:00:00+00:00 [timeZone] => America/Sao_Paulo ) [end] => Array ( [dateTime] => 2023-04-01T02:59:59+00:00 [timeZone] => America/Sao_Paulo ) )
推荐实践:用PHP DateTime类处理时区
避免手动计算时区偏移出错,用DateTime类自动生成正确的ISO格式时间:
// 创建圣保罗时区的起始时间 $startDateTime = new DateTime('2023-03-30 00:00:00', new DateTimeZone('America/Sao_Paulo')); // 创建圣保罗时区的结束时间 $endDateTime = new DateTime('2023-03-31 23:59:59', new DateTimeZone('America/Sao_Paulo')); // 构建事件数组 $event = [ 'summary' => 'test', 'location' => 'test', 'description' => 'test', 'start' => [ 'dateTime' => $startDateTime->format(DateTimeInterface::RFC3339), 'timeZone' => 'America/Sao_Paulo' ], 'end' => [ 'dateTime' => $endDateTime->format(DateTimeInterface::RFC3339), 'timeZone' => 'America/Sao_Paulo' ] ];
内容的提问来源于stack exchange,提问作者diogo.abdalla
相关产品推荐
相关产品推荐

