如何在 Java 中设置 iCalendar 的时区?

How to set the Timezone for iCalendar in Java?

我有以下代码使用 biweekly 库来为我的 Java 应用程序中的事件创建 ical

ical 已按预期通过电子邮件发送,但它始终在 GMT 中,我目前正在尝试将其设置为 "America/New_York",如下所示,但它不起作用.

我该怎么做?

    private String generateIcal(Appointment appointment) {
    
      ICalendar ical = new ICalendar();
      VEvent event = new VEvent();
    
      event.setDateStart(appointment.getEventStartDatetime()); //value of: 2021-01-07 01:01:00
      event.setDateEnd(appointment.getEventEndDatetime()); //value of: 2021-01-07 23:59:00
      event.setDescription(appointment.getDescription());
      event.setSummary(appointment.getTitle());
    
      ical.addEvent(event);

      String id = "America/New_York";
      TimeZone timezone = TimeZone.getTimeZone(id);

      return Biweekly.write(ical).tz(timezone, false).go();

 }

ics文件内容:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Michael Angstadt//biweekly 0.6.5//EN
BEGIN:VTIMEZONE
TZID:America/New_York
LAST-MODIFIED:20201011T015911Z
TZURL:http://tzurl.org/zoneinfo/America/New_York
X-LIC-LOCATION:America/New_York
X-PROLEPTIC-TZNAME:LMT
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0456
TZOFFSETTO:-0500
DTSTART:18831118T120358
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19201031T060000Z;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:19450930T020000
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:STANDARD
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19200328T070000Z;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19420209T020000
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
DTSTART:19450814T190000
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19740106T020000
RDATE:19750223T020000
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
END:DAYLIGHT
BEGIN:DAYLIGHT
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
UID:c59d5d8b-884a-4467-a80b-6eed29e8c94f
DTSTAMP:20210106T092518Z
DTSTART;TZID=America/New_York:20210106T200100
DTEND;TZID=America/New_York:20210107T185900
DESCRIPTION: test event
SUMMARY: test Summary
END:VEVENT
END:VCALENDAR

Gmail 邀请:

请注意,下面显示的邀请是我当地时间 (GMT) 的 1.01am,但实际上应该显示 1.01am + 5 hours,因为格林威治标准时间比纽约时区早 5 小时。

您可以在链接 API 中使用 tz 方法为所有属性设置默认输出时区。

ICalendar ical = ...
String id = "America/New_York";
TimeZone timezone = TimeZone.getTimeZone(id);
Biweekly.write(ical).tz(timezone, false).go(System.out);

邀请设置为:

DTSTART;TZID=America/New_York:20210106T200100
DTEND;TZID=America/New_York:20210107T185900

这表示活动从 8:01pm 在纽约开始。您为 America/New_York 设置的时区偏移量为 -500 所以这就是说这次 20210107T185900 偏移 -500(比 UTC 晚 5 小时)。

然后您将在 Gmail 日历中打开邀请,它会自动将其转换为 GMT 时区(基于您本地计算机的日期时间设置)。这就是为什么它显示为 1:01am (GMT)。