diff --git a/sagan-site/src/main/java/sagan/site/events/Event.java b/sagan-site/src/main/java/sagan/site/events/Event.java index 0cc3967fa..169919412 100644 --- a/sagan-site/src/main/java/sagan/site/events/Event.java +++ b/sagan-site/src/main/java/sagan/site/events/Event.java @@ -1,16 +1,17 @@ package sagan.site.events; import java.net.URI; -import java.time.ZonedDateTime; -import java.util.TimeZone; +import java.time.Duration; +import java.time.LocalDate; +import java.time.ZoneId; import biweekly.component.VEvent; -public class Event { +public class Event implements Comparable { - private final ZonedDateTime startTime; + private final LocalDate firstDay; - private final ZonedDateTime endTime; + private final LocalDate lastDay; private final String summary; @@ -18,17 +19,17 @@ public class Event { private final String location; - protected Event(ZonedDateTime startTime, ZonedDateTime endTime, String summary, URI link, String location) { - this.startTime = startTime; - this.endTime = endTime; + protected Event(LocalDate firstDay, LocalDate lastDay, String summary, URI link, String location) { + this.firstDay = firstDay; + this.lastDay = lastDay; this.summary = summary; this.link = link; this.location = location; } - protected Event(VEvent event, TimeZone timeZone) { - this.startTime = ZonedDateTime.ofInstant(event.getDateStart().getValue().toInstant(), timeZone.toZoneId()); - this.endTime = ZonedDateTime.ofInstant(event.getDateEnd().getValue().toInstant(), timeZone.toZoneId()); + protected Event(VEvent event) { + this.firstDay = event.getDateStart().getValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + this.lastDay = event.getDateEnd().getValue().toInstant().minus(Duration.ofMinutes(1)).atZone(ZoneId.systemDefault()).toLocalDate(); this.summary = event.getSummary().getValue(); this.link = parseLink(event); this.location = event.getLocation().getValue(); @@ -43,24 +44,32 @@ private URI parseLink(VEvent event) { } } - public ZonedDateTime getStartTime() { - return startTime; + public LocalDate getFirstDay() { + return this.firstDay; } - public ZonedDateTime getEndTime() { - return endTime; + public LocalDate getLastDay() { + return this.lastDay; + } + + public boolean isSingleDayEvent() { + return this.firstDay.equals(this.lastDay); } public String getSummary() { - return summary; + return this.summary; } public URI getLink() { - return link; + return this.link; } public String getLocation() { - return location; + return this.location; } + @Override + public int compareTo(Event other) { + return this.firstDay.compareTo(other.firstDay); + } } diff --git a/sagan-site/src/main/java/sagan/site/events/EventsCalendarService.java b/sagan-site/src/main/java/sagan/site/events/EventsCalendarService.java index d4df81411..e50ce989e 100644 --- a/sagan-site/src/main/java/sagan/site/events/EventsCalendarService.java +++ b/sagan-site/src/main/java/sagan/site/events/EventsCalendarService.java @@ -1,9 +1,7 @@ package sagan.site.events; import java.net.URI; -import java.util.Comparator; import java.util.List; -import java.util.TimeZone; import java.util.stream.Collectors; import biweekly.Biweekly; @@ -34,12 +32,11 @@ public List findEvents(Period period) { try { String rawCalendar = this.client.getForEntity(this.calendarUri.toString(), String.class).getBody(); ICalendar iCalendar = Biweekly.parse(rawCalendar).first(); - TimeZone calendarTimeZone = getCalendarTimeZone(iCalendar); List events = iCalendar.getEvents(); return events.stream() .filter(period.toCalendarFilter()) - .map(event -> new Event(event, calendarTimeZone)) - .sorted(Comparator.comparingLong(event -> event.getStartTime().toInstant().toEpochMilli())) + .map(Event::new) + .sorted() .collect(Collectors.toList()); } catch (HttpClientErrorException ex) { @@ -50,13 +47,4 @@ public List findEvents(Period period) { } } - private TimeZone getCalendarTimeZone(ICalendar iCalendar) { - if (iCalendar.getTimezoneInfo().getDefaultTimezone() != null) { - return iCalendar.getTimezoneInfo().getDefaultTimezone().getTimeZone(); - } - if (iCalendar.getExperimentalProperties("X-WR-TIMEZONE").size() > 0) { - return TimeZone.getTimeZone(iCalendar.getExperimentalProperties("X-WR-TIMEZONE").get(0).getValue()); - } - return TimeZone.getDefault(); - } } diff --git a/sagan-site/src/test/java/sagan/site/events/EventsCalendarServiceTests.java b/sagan-site/src/test/java/sagan/site/events/EventsCalendarServiceTests.java index f81267824..60bc89a31 100644 --- a/sagan-site/src/test/java/sagan/site/events/EventsCalendarServiceTests.java +++ b/sagan-site/src/test/java/sagan/site/events/EventsCalendarServiceTests.java @@ -1,6 +1,5 @@ package sagan.site.events; - import java.util.List; import org.junit.Test; @@ -71,8 +70,8 @@ public void shouldReturnSingleEvent() { assertThat(events).hasSize(1); Event event = events.get(0); assertThat(event.getSummary()).isEqualTo("Spring IO conference"); - assertThat(event.getStartTime().toString()).isEqualTo("2020-05-14T00:00-07:00[America/Los_Angeles]"); - assertThat(event.getEndTime().toString()).isEqualTo("2020-05-15T09:00-07:00[America/Los_Angeles]"); + assertThat(event.getFirstDay().toString()).isEqualTo("2020-05-14"); + assertThat(event.getLastDay().toString()).isEqualTo("2020-05-15"); assertThat(event.getLocation()).isEqualTo("Barcelona, Spain"); assertThat(event.getLink().toString()).isEqualTo("https://springio.net"); } @@ -84,11 +83,19 @@ public void shouldReturnManyEvents() { List events = this.calendarService.findEvents(Period.of("2020-05-01", 30)); assertThat(events).hasSize(2); Event event = events.get(0); - assertThat(event.getSummary()).isEqualTo("Spring @ San Francisco JUG"); - assertThat(event.getStartTime().toString()).isEqualTo("2020-05-11T18:00-07:00[America/Los_Angeles]"); - assertThat(event.getEndTime().toString()).isEqualTo("2020-05-11T21:00-07:00[America/Los_Angeles]"); - assertThat(event.getLocation()).isEqualTo("San Francisco, California"); - assertThat(event.getLink().toString()).isEqualTo("https://spring.io"); + assertThat(event.getSummary()).isEqualTo("Spring IO conference"); + assertThat(event.getFirstDay().toString()).isEqualTo("2020-05-14"); + assertThat(event.getLastDay().toString()).isEqualTo("2020-05-15"); + assertThat(event.isSingleDayEvent()).isFalse(); + assertThat(event.getLocation()).isEqualTo("Barcelona, Spain"); + assertThat(event.getLink().toString()).isEqualTo("https://springio.net"); + event = events.get(1); + assertThat(event.getSummary()).isEqualTo("Sample Event"); + assertThat(event.getFirstDay().toString()).isEqualTo("2020-05-20"); + assertThat(event.getLastDay().toString()).isEqualTo("2020-05-20"); + assertThat(event.isSingleDayEvent()).isTrue(); + assertThat(event.getLocation()).isEqualTo("Seattle, WA, USA"); + assertThat(event.getLink().toString()).isEqualTo("https://example.org/sample"); } private ClassPathResource getClassPathResource(String path) { diff --git a/sagan-site/src/test/resources/sagan/site/events/multi-events.ics b/sagan-site/src/test/resources/sagan/site/events/multi-events.ics index 2008b75b9..1c9cc98e9 100644 --- a/sagan-site/src/test/resources/sagan/site/events/multi-events.ics +++ b/sagan-site/src/test/resources/sagan/site/events/multi-events.ics @@ -6,31 +6,45 @@ METHOD:PUBLISH X-WR-CALNAME:Spring Events X-WR-TIMEZONE:America/Los_Angeles BEGIN:VEVENT -DTSTART:20200512T010000Z -DTEND:20200512T040000Z -DTSTAMP:20200128T141410Z -UID:jug-event@example.org -CREATED:20200128T135531Z -DESCRIPTION:https://spring.io -LAST-MODIFIED:20200128T141357Z -LOCATION:San Francisco\, California -SEQUENCE:2 -STATUS:CONFIRMED -SUMMARY:Spring @ San Francisco JUG -TRANSP:OPAQUE -END:VEVENT -BEGIN:VEVENT -DTSTART:20200514T070000Z -DTEND:20200515T160000Z -DTSTAMP:20200128T141410Z -UID:springio-event@example.org +DTSTART;VALUE=DATE:20200514 +DTEND;VALUE=DATE:20200516 +DTSTAMP:20200211T210141Z +UID:springio@example.org CREATED:20200128T095717Z DESCRIPTION:https://springio.net -LAST-MODIFIED:20200128T140810Z +LAST-MODIFIED:20200211T210129Z LOCATION:Barcelona\, Spain -SEQUENCE:1 +SEQUENCE:2 STATUS:CONFIRMED SUMMARY:Spring IO conference TRANSP:TRANSPARENT END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20200520 +DTEND;VALUE=DATE:20200521 +DTSTAMP:20200211T210141Z +UID:sample@example.org +CREATED:20200201T145735Z +DESCRIPTION:https://example.org/sample +LAST-MODIFIED:20200204T084706Z +LOCATION:Seattle\, WA\, USA +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sample Event +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20200309 +DTEND;VALUE=DATE:20200311 +DTSTAMP:20200211T210141Z +UID:s1t-seattle@example.org +CREATED:20200201T145735Z +DESCRIPTION:https://springonetour.io/2020/seattle +LAST-MODIFIED:20200204T084706Z +LOCATION:Seattle\, WA\, USA +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:SpringOneTour Seattle +TRANSP:TRANSPARENT +END:VEVENT END:VCALENDAR diff --git a/sagan-site/src/test/resources/sagan/site/events/single-event.ics b/sagan-site/src/test/resources/sagan/site/events/single-event.ics index 7351e1b89..78d1f938e 100644 --- a/sagan-site/src/test/resources/sagan/site/events/single-event.ics +++ b/sagan-site/src/test/resources/sagan/site/events/single-event.ics @@ -6,17 +6,18 @@ METHOD:PUBLISH X-WR-CALNAME:Spring Events X-WR-TIMEZONE:America/Los_Angeles BEGIN:VEVENT -DTSTART:20200514T070000Z -DTEND:20200515T160000Z -DTSTAMP:20200128T141410Z +DTSTART;VALUE=DATE:20200514 +DTEND;VALUE=DATE:20200516 +DTSTAMP:20200211T210141Z UID:springio-event@example.org CREATED:20200128T095717Z DESCRIPTION:https://springio.net -LAST-MODIFIED:20200128T140810Z +LAST-MODIFIED:20200211T210129Z LOCATION:Barcelona\, Spain -SEQUENCE:1 +SEQUENCE:2 STATUS:CONFIRMED SUMMARY:Spring IO conference TRANSP:TRANSPARENT END:VEVENT + END:VCALENDAR