[icalendar] Short events parallel to longer current events are now also shown as current event (#10810)
Signed-off-by: Michael Wodniok <michi@noorganization.org>
This commit is contained in:
parent
503abab181
commit
6b324d6701
@ -65,6 +65,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Michael Wodniok - Initial contribution
|
* @author Michael Wodniok - Initial contribution
|
||||||
* @author Andrew Fiddian-Green - Support for Command Tags embedded in the Event description
|
* @author Andrew Fiddian-Green - Support for Command Tags embedded in the Event description
|
||||||
* @author Michael Wodniok - Added last_update-channel and additional needed handling of it
|
* @author Michael Wodniok - Added last_update-channel and additional needed handling of it
|
||||||
|
* @author Michael Wodniok - Changed calculation of Future for refresh of channels
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class ICalendarHandler extends BaseBridgeHandler implements CalendarUpdateListener {
|
public class ICalendarHandler extends BaseBridgeHandler implements CalendarUpdateListener {
|
||||||
@ -337,6 +338,7 @@ public class ICalendarHandler extends BaseBridgeHandler implements CalendarUpdat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Instant now = Instant.now();
|
final Instant now = Instant.now();
|
||||||
|
Instant nextRegularUpdate = null;
|
||||||
if (currentCalendar.isEventPresent(now)) {
|
if (currentCalendar.isEventPresent(now)) {
|
||||||
final Event currentEvent = currentCalendar.getCurrentEvent(now);
|
final Event currentEvent = currentCalendar.getCurrentEvent(now);
|
||||||
if (currentEvent == null) {
|
if (currentEvent == null) {
|
||||||
@ -344,12 +346,9 @@ public class ICalendarHandler extends BaseBridgeHandler implements CalendarUpdat
|
|||||||
"Could not schedule next update of states, due to unexpected behaviour of calendar implementation.");
|
"Could not schedule next update of states, due to unexpected behaviour of calendar implementation.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateJobFuture = scheduler.schedule(() -> {
|
nextRegularUpdate = currentEvent.end;
|
||||||
ICalendarHandler.this.updateStates();
|
}
|
||||||
ICalendarHandler.this.rescheduleCalendarStateUpdate();
|
|
||||||
}, currentEvent.end.getEpochSecond() - now.getEpochSecond(), TimeUnit.SECONDS);
|
|
||||||
logger.debug("Scheduled update in {} seconds", currentEvent.end.getEpochSecond() - now.getEpochSecond());
|
|
||||||
} else {
|
|
||||||
final Event nextEvent = currentCalendar.getNextEvent(now);
|
final Event nextEvent = currentCalendar.getNextEvent(now);
|
||||||
final ICalendarConfiguration currentConfig = this.configuration;
|
final ICalendarConfiguration currentConfig = this.configuration;
|
||||||
if (currentConfig == null) {
|
if (currentConfig == null) {
|
||||||
@ -357,19 +356,23 @@ public class ICalendarHandler extends BaseBridgeHandler implements CalendarUpdat
|
|||||||
"Something is broken, the configuration is not available.");
|
"Something is broken, the configuration is not available.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nextEvent == null) {
|
if (nextEvent != null) {
|
||||||
|
if (nextRegularUpdate == null || nextEvent.start.isBefore(nextRegularUpdate)) {
|
||||||
|
nextRegularUpdate = nextEvent.start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextRegularUpdate != null) {
|
||||||
|
updateJobFuture = scheduler.schedule(() -> {
|
||||||
|
ICalendarHandler.this.updateStates();
|
||||||
|
ICalendarHandler.this.rescheduleCalendarStateUpdate();
|
||||||
|
}, nextRegularUpdate.getEpochSecond() - now.getEpochSecond(), TimeUnit.SECONDS);
|
||||||
|
logger.debug("Scheduled update in {} seconds", nextRegularUpdate.getEpochSecond() - now.getEpochSecond());
|
||||||
|
} else {
|
||||||
updateJobFuture = scheduler.schedule(() -> {
|
updateJobFuture = scheduler.schedule(() -> {
|
||||||
ICalendarHandler.this.rescheduleCalendarStateUpdate();
|
ICalendarHandler.this.rescheduleCalendarStateUpdate();
|
||||||
}, 1L, TimeUnit.DAYS);
|
}, 1L, TimeUnit.DAYS);
|
||||||
logger.debug("Scheduled reschedule in 1 day");
|
logger.debug("Scheduled reschedule in 1 day");
|
||||||
} else {
|
|
||||||
updateJobFuture = scheduler.schedule(() -> {
|
|
||||||
ICalendarHandler.this.updateStates();
|
|
||||||
ICalendarHandler.this.rescheduleCalendarStateUpdate();
|
|
||||||
}, nextEvent.start.getEpochSecond() - now.getEpochSecond(), TimeUnit.SECONDS);
|
|
||||||
logger.debug("Scheduled update in {} seconds", nextEvent.start.getEpochSecond() - now.getEpochSecond());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,6 +59,8 @@ import biweekly.util.com.google.ical.compat.javautil.DateIterator;
|
|||||||
* @author Andrew Fiddian-Green - Methods getJustBegunEvents() & getJustEndedEvents()
|
* @author Andrew Fiddian-Green - Methods getJustBegunEvents() & getJustEndedEvents()
|
||||||
* @author Michael Wodniok - Extension for filtered events
|
* @author Michael Wodniok - Extension for filtered events
|
||||||
* @author Michael Wodniok - Added logic for events moved with "RECURRENCE-ID" (issue 9647)
|
* @author Michael Wodniok - Added logic for events moved with "RECURRENCE-ID" (issue 9647)
|
||||||
|
* @author Michael Wodniok - Extended logic for defined behavior with parallel current events
|
||||||
|
* (issue 10808)
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
class BiweeklyPresentableCalendar extends AbstractPresentableCalendar {
|
class BiweeklyPresentableCalendar extends AbstractPresentableCalendar {
|
||||||
@ -320,6 +322,8 @@ class BiweeklyPresentableCalendar extends AbstractPresentableCalendar {
|
|||||||
final List<VEvent> positiveEvents = new ArrayList<VEvent>();
|
final List<VEvent> positiveEvents = new ArrayList<VEvent>();
|
||||||
classifyEvents(positiveEvents, negativeEvents);
|
classifyEvents(positiveEvents, negativeEvents);
|
||||||
|
|
||||||
|
VEventWPeriod earliestEndingEvent = null;
|
||||||
|
|
||||||
for (final VEvent currentEvent : positiveEvents) {
|
for (final VEvent currentEvent : positiveEvents) {
|
||||||
final DateIterator startDates = this.getRecurredEventDateIterator(currentEvent);
|
final DateIterator startDates = this.getRecurredEventDateIterator(currentEvent);
|
||||||
final Duration duration = getEventLength(currentEvent);
|
final Duration duration = getEventLength(currentEvent);
|
||||||
@ -333,7 +337,9 @@ class BiweeklyPresentableCalendar extends AbstractPresentableCalendar {
|
|||||||
if (startInstant.isBefore(instant) && endInstant.isAfter(instant)) {
|
if (startInstant.isBefore(instant) && endInstant.isAfter(instant)) {
|
||||||
final Uid eventUid = currentEvent.getUid();
|
final Uid eventUid = currentEvent.getUid();
|
||||||
if (eventUid == null || !isCounteredBy(startInstant, eventUid, negativeEvents)) {
|
if (eventUid == null || !isCounteredBy(startInstant, eventUid, negativeEvents)) {
|
||||||
return new VEventWPeriod(currentEvent, startInstant, endInstant);
|
if (earliestEndingEvent == null || endInstant.isBefore(earliestEndingEvent.end)) {
|
||||||
|
earliestEndingEvent = new VEventWPeriod(currentEvent, startInstant, endInstant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startInstant.isAfter(instant.plus(duration))) {
|
if (startInstant.isAfter(instant.plus(duration))) {
|
||||||
@ -342,7 +348,7 @@ class BiweeklyPresentableCalendar extends AbstractPresentableCalendar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return earliestEndingEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,13 +41,14 @@ import org.openhab.core.types.Command;
|
|||||||
* @author Michael Wodniok - Initial contribution.
|
* @author Michael Wodniok - Initial contribution.
|
||||||
* @author Andrew Fiddian-Green - Tests for Command Tag code
|
* @author Andrew Fiddian-Green - Tests for Command Tag code
|
||||||
* @author Michael Wodniok - Extended Tests for filtered Events
|
* @author Michael Wodniok - Extended Tests for filtered Events
|
||||||
*
|
* @author Michael Wodniok - Extended Test for parallel current events
|
||||||
*/
|
*/
|
||||||
public class BiweeklyPresentableCalendarTest {
|
public class BiweeklyPresentableCalendarTest {
|
||||||
private AbstractPresentableCalendar calendar;
|
private AbstractPresentableCalendar calendar;
|
||||||
private AbstractPresentableCalendar calendar2;
|
private AbstractPresentableCalendar calendar2;
|
||||||
private AbstractPresentableCalendar calendar3;
|
private AbstractPresentableCalendar calendar3;
|
||||||
private AbstractPresentableCalendar calendar_issue9647;
|
private AbstractPresentableCalendar calendar_issue9647;
|
||||||
|
private AbstractPresentableCalendar calendar_issue10808;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() throws IOException, CalendarException {
|
public void setUp() throws IOException, CalendarException {
|
||||||
@ -56,6 +57,8 @@ public class BiweeklyPresentableCalendarTest {
|
|||||||
calendar3 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test3.ics"));
|
calendar3 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test3.ics"));
|
||||||
calendar_issue9647 = new BiweeklyPresentableCalendar(
|
calendar_issue9647 = new BiweeklyPresentableCalendar(
|
||||||
new FileInputStream("src/test/resources/test-issue9647.ics"));
|
new FileInputStream("src/test/resources/test-issue9647.ics"));
|
||||||
|
calendar_issue10808 = new BiweeklyPresentableCalendar(
|
||||||
|
new FileInputStream("src/test/resources/test-issue10808.ics"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,6 +120,18 @@ public class BiweeklyPresentableCalendarTest {
|
|||||||
|
|
||||||
Event nonExistingEvent = calendar.getCurrentEvent(Instant.parse("2019-09-09T09:07:00Z"));
|
Event nonExistingEvent = calendar.getCurrentEvent(Instant.parse("2019-09-09T09:07:00Z"));
|
||||||
assertNull(nonExistingEvent);
|
assertNull(nonExistingEvent);
|
||||||
|
|
||||||
|
Event currentEvent2 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:10:05Z"));
|
||||||
|
assertNotNull(currentEvent2);
|
||||||
|
assertTrue("Test event 1".contentEquals(currentEvent2.title));
|
||||||
|
|
||||||
|
Event currentEvent3 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:13:05Z"));
|
||||||
|
assertNotNull(currentEvent3);
|
||||||
|
assertTrue("Test event 2".contentEquals(currentEvent3.title));
|
||||||
|
|
||||||
|
Event currentEvent4 = calendar_issue10808.getCurrentEvent(Instant.parse("2021-06-05T17:18:05Z"));
|
||||||
|
assertNotNull(currentEvent4);
|
||||||
|
assertTrue("Test event 1".contentEquals(currentEvent4.title));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
CALSCALE:GREGORIAN
|
||||||
|
PRODID:-//SabreDAV//SabreDAV//EN
|
||||||
|
X-WR-CALNAME:Test
|
||||||
|
X-APPLE-CALENDAR-COLOR:#499AA2
|
||||||
|
REFRESH-INTERVAL;VALUE=DURATION:PT4H
|
||||||
|
X-PUBLISHED-TTL:PT4H
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:Europe/Paris
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
TZOFFSETFROM:+0100
|
||||||
|
TZOFFSETTO:+0200
|
||||||
|
TZNAME:CEST
|
||||||
|
DTSTART:19700329T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:STANDARD
|
||||||
|
TZOFFSETFROM:+0200
|
||||||
|
TZOFFSETTO:+0100
|
||||||
|
TZNAME:CET
|
||||||
|
DTSTART:19701025T030000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||||
|
END:STANDARD
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20210107T155730Z
|
||||||
|
DTSTAMP:20210107T160226Z
|
||||||
|
LAST-MODIFIED:20210605T163408Z
|
||||||
|
SEQUENCE:4
|
||||||
|
UID:bd676ec9-0cdb-4c8d-a6dd-9e3fcf77a45f
|
||||||
|
DTSTART;TZID=Europe/Paris:20210605T191000
|
||||||
|
DTEND;TZID=Europe/Paris:20210605T192000
|
||||||
|
SUMMARY:Test event 1
|
||||||
|
DESCRIPTION:BEGIN:DemoString:EHLO1
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20210107T160405Z
|
||||||
|
DTSTAMP:20210107T160405Z
|
||||||
|
LAST-MODIFIED:20210605T163512Z
|
||||||
|
UID:7d1ecca5-1ddd-4932-b096-d034c8d7f5aa
|
||||||
|
DTSTART;TZID=Europe/Paris:20210605T191200
|
||||||
|
DTEND;TZID=Europe/Paris:20210605T191600
|
||||||
|
SUMMARY:Test event 2
|
||||||
|
DESCRIPTION:BEGIN:DemoString:EHLO2
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
Loading…
x
Reference in New Issue
Block a user