【问题标题】:How to set the Timezone for iCalendar in Java?如何在 Java 中为 iCalendar 设置时区?
【发布时间】:2021-04-11 11:54:39
【问题描述】:

我有以下代码使用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,因为 GMT 比纽约时区早 5 小时。

【问题讨论】:

  • "DTSTART;TZID=America/New_York:20210106T200100" - 这是纽约时间晚上 8:01,也就是格林威治标准时间凌晨 1:01,正如我所期望的那样。听起来您预计是纽约时间凌晨 1:01,但这不是您的 ICS 文件显示的内容。我们不知道appointment.getEventStartDatetime() 是什么,这无济于事。
  • 是的,我预计 ICal 将在纽约时间凌晨 1 点显示。我现在已经更新了我的代码以显示开始时间和结束时间的值,我只是很困惑为什么开始时间显示为我的 1.01 我的本地时间 (GMT) 而不是纽约时间。谢谢
  • appointment.getEventStartDatetime()type 是什么? (我不太了解 iCalendar 库。)同样Biweekly.write(ical).tz(timezone, false) 涉及哪些类型?
  • 如果有一个minimal reproducible example 会很好 - 一个简单的控制台应用程序,不需要任何用户输入,但会输出 iCal 条目(在控制台上)。这将使重现问题变得更容易。鉴于 iCal 条目,看起来 gmail 邀请的行为正确。
  • getEventStartDateTime 返回一个标准的 Java 日期,Biweekly.write(ical) 返回一个 ChainingTextWriter,然后调用 .tz() 方法。这可以在这里看到:mangstadt.github.io/biweekly/javadocs/0.6.1/index.html?biweekly/…

标签: java timezone icalendar biweekly


【解决方案1】:

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

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

【讨论】:

  • 我已经尝试过了,但是我遇到了同样的问题,时区总是作为 GMT 出现?我已经更新了上面的代码
  • 我还添加了 ics 文件内容,注意我使用的是 google chrome。
  • @java12399900 我看不出是什么问题?您在编辑后的答案中包含的输出对我来说看起来是正确的。 DTSTART 和 DTEND 属性分配给 Americal/New_York 时区定义。
  • 我也注意到了,但我现在添加了 Gmail 的活动邀请的屏幕截图,注意它是 GMT 时间?感谢您的帮助,因为我知道您是图书馆的创建者 :)
  • 请参阅我对 Jon Skeets 评论的回复,它将进一步解释我的意思。
【解决方案2】:

邀请设置为:

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

这表明该活动从晚上 8:01 在纽约开始。您为 America/New_York 设置的时区具有 -500 的偏移量,所以这意味着 20210107T185900 的时间是偏移 -500(比 UTC 晚 5 小时)。

然后,您将在 Gmail 日历中打开邀请,该日历会自动将其转换为 GMT 时区(根据您本地计算机的日期时间设置)。这就是为什么它显示为凌晨 1:01(格林威治标准时间)。

【讨论】:

    猜你喜欢
    • 2011-10-24
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多