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

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;
    }
}

关键注意事项

  1. 区分两种事件类型:必须用hasDateTime()和hasDate()判断字段是否存在,不要直接取值
  2. 全天事件的结束日期修正:Google Calendar的全天事件结束日期是设定结束日的次日(比如你创建5.20-5.22的全天事件,Google返回的end date是5.23),所以转换结束时间时一定要减一天,否则展示会出错
  3. 时区处理:用OffsetDateTime可以正确解析Google返回的带时区的时间,避免时区偏移导致的时间错误
  4. 自定义格式:你可以修改DATE_FORMATTER和DATE_TIME_FORMATTER的格式串,改成你自研日历需要的格式(比如MM/dd/yyyy hh:mm a)

排查小技巧

如果还是出现null,你可以先打印event.getStart()的完整内容,看看它到底是填充了date还是dateTime字段,这样就能快速定位问题。

内容的提问来源于stack exchange,提问作者Sachin HR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:00:38