Spring Controller中转换Google Calendar API返回的日期时间格式
解决Google Calendar API日期转换为指定格式的问题
看起来你遇到的核心问题是没处理好Google Calendar API返回的两种日期类型——带时间的事件和全天事件,这两种事件的start/end字段结构不一样,直接取某一个字段自然会返回null。我来给你一步步解决这个问题:
问题根源
Google Calendar的Event对象里,start和end属性是EventDateTime类型,它有两种存储方式:
- 非全天事件:会填充
dateTime字段(ISO 8601格式,比如2024-05-20T14:30:00+08:00) - 全天事件:只会填充
date字段(纯日期格式,比如2024-05-20)
如果你直接调用start.getDateTime()去拿全天事件的时间,肯定会返回null,这就是你控制台打印出null的原因。
正确的转换代码(Spring MVC Controller示例)
下面是完整的处理逻辑,我用Java 8的时间API来处理(比旧的Date类更可靠),你可以直接整合到你的Controller里:
import com.google.api.services.calendar.model.Event; import com.google.api.services.calendar.model.EventDateTime; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; @Controller public class CalendarSyncController { // 自定义你需要的日期格式,比如"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss" private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @GetMapping("/sync-calendar") public String syncCalendarEvents() { // 假设这里是你已经获取到的Google Calendar事件列表 // List<Event> events = googleCalendarService.fetchAllEvents(); for (Event event : events) { String startDateStr = convertEventDate(event.getStart(), false); String endDateStr = convertEventDate(event.getEnd(), true); System.out.println("开始时间:" + startDateStr); System.out.println("结束时间:" + endDateStr); // 这里把转换后的日期存入你的自研日历模型,再返回给前端 } return "calendar-view"; } /** * 统一处理Google EventDateTime的转换逻辑 * @param isEndDate 是否为结束日期(用于修正全天事件的结束日) */ private String convertEventDate(EventDateTime eventDateTime, boolean isEndDate) { if (eventDateTime == null) { return null; } // 处理带时间的事件 if (eventDateTime.hasDateTime()) { OffsetDateTime dateTime = eventDateTime.getDateTime().toOffsetDateTime(); return dateTime.format(DATE_TIME_FORMATTER); } // 处理全天事件 else if (eventDateTime.hasDate()) { LocalDate date = eventDateTime.getDate().toLocalDate(); // 全天事件的结束日期是设定结束日的次日,需要减1天修正 if (isEndDate) { date = date.minusDays(1); } return date.format(DATE_FORMATTER); } return null; } }
关键注意事项
- 区分两种事件类型:必须用
hasDateTime()和hasDate()判断字段是否存在,不要直接取值 - 全天事件的结束日期修正:Google Calendar的全天事件结束日期是设定结束日的次日(比如你创建5.20-5.22的全天事件,Google返回的end date是5.23),所以转换结束时间时一定要减一天,否则展示会出错
- 时区处理:用
OffsetDateTime可以正确解析Google返回的带时区的时间,避免时区偏移导致的时间错误 - 自定义格式:你可以修改
DATE_FORMATTER和DATE_TIME_FORMATTER的格式串,改成你自研日历需要的格式(比如MM/dd/yyyy hh:mm a)
排查小技巧
如果还是出现null,你可以先打印event.getStart()的完整内容,看看它到底是填充了date还是dateTime字段,这样就能快速定位问题。
内容的提问来源于stack exchange,提问作者Sachin HR
相关产品推荐
相关产品推荐

