diff --git a/modules/core/.jvm/src/test/resources/com/github/eikek/calev/trigger-data.txt b/modules/core/.jvm/src/test/resources/com/github/eikek/calev/trigger-data.txt index 9e128e1..673f599 100644 --- a/modules/core/.jvm/src/test/resources/com/github/eikek/calev/trigger-data.txt +++ b/modules/core/.jvm/src/test/resources/com/github/eikek/calev/trigger-data.txt @@ -87,3 +87,10 @@ Mon *-*-* *:10,20,50 1900-01-* 12,14:0:0 2021-01-06T20:39:23.001+01:00[Europe/Berlin] + +2021-11-15 21:05:00 Europe/Berlin +2021-11-15T21:10:00Z + +2021-11-15 21:05:00 Europe/Berlin +2021-11-15T20:00:00Z +2021-11-15T20:05:00Z \ No newline at end of file diff --git a/modules/core/src/main/scala/com/github/eikek/calev/CalEvent.scala b/modules/core/src/main/scala/com/github/eikek/calev/CalEvent.scala index d5984ba..08fb549 100644 --- a/modules/core/src/main/scala/com/github/eikek/calev/CalEvent.scala +++ b/modules/core/src/main/scala/com/github/eikek/calev/CalEvent.scala @@ -1,9 +1,6 @@ package com.github.eikek.calev -import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneId -import java.time.ZonedDateTime +import java.time._ final case class CalEvent( weekday: WeekdayComponent, @@ -56,7 +53,7 @@ final case class CalEvent( object CalEvent { - val UTC = ZoneId.of("UTC") + val UTC: ZoneId = ZoneOffset.UTC def parse(str: String): Either[String, CalEvent] = internal.CalEventParser.calevent.run(str.trim).map(_._2) diff --git a/modules/core/src/main/scala/com/github/eikek/calev/internal/DefaultTrigger.scala b/modules/core/src/main/scala/com/github/eikek/calev/internal/DefaultTrigger.scala index 4dccff0..1194cfd 100644 --- a/modules/core/src/main/scala/com/github/eikek/calev/internal/DefaultTrigger.scala +++ b/modules/core/src/main/scala/com/github/eikek/calev/internal/DefaultTrigger.scala @@ -28,19 +28,21 @@ import com.github.eikek.calev._ object DefaultTrigger extends Trigger { def next(ref: ZonedDateTime, ev: CalEvent): Option[ZonedDateTime] = { - val refDate = { + val (refDate, zone) = { val date = ev.zone .map(z => ref.withZoneSameInstant(z)) .getOrElse(ref) - DateTime(date.toLocalDateTime) + (DateTime(date.toLocalDateTime), date.getZone) } @annotation.tailrec def go(c: Calc): Option[ZonedDateTime] = run(c) match { case Some(dt) => - val zd = dt.toLocalDateTime.atZone(ref.getZone) - if (ev.weekday.contains(Weekday.from(zd.getDayOfWeek))) Some(zd) + val zd = dt.toLocalDateTime.atZone(zone) + // need to match weekdays in the zone of the calendar-event + if (ev.weekday.contains(Weekday.from(zd.getDayOfWeek))) + Some(zd.withZoneSameInstant(ref.getZone)) else go(Calc.init(dt, ev)) case None => None diff --git a/modules/core/src/test/scala/com/github/eikek/calev/CalEventTest.scala b/modules/core/src/test/scala/com/github/eikek/calev/CalEventTest.scala index 465a2dd..c46a586 100644 --- a/modules/core/src/test/scala/com/github/eikek/calev/CalEventTest.scala +++ b/modules/core/src/test/scala/com/github/eikek/calev/CalEventTest.scala @@ -1,8 +1,6 @@ package com.github.eikek.calev -import java.time.LocalDate -import java.time.LocalTime -import java.time.ZonedDateTime +import java.time._ import java.time.temporal.ChronoField import com.github.eikek.calev.Dsl._ @@ -67,6 +65,21 @@ class CalEventTest extends FunSuite { assertEquals(ce.nextElapses(ref, 5), expect) } + test("nextElapse honors time zones") { + val ref = zdt(2022, 2, 28, 21, 5, 15) + + val ce = CalEvent( + AllWeekdays, + DateEvent.All, + time(22.c, 10.c, 0.c), + Some(ZoneId.of("Europe/Berlin")) + ) + + val Some(next) = ce.nextElapse(ref) + assertEquals(next.getZone, ZoneOffset.UTC) + assertEquals(next.toLocalTime, LocalTime.of(21, 10, 0)) + } + private def zdt(y: Int, month: Int, d: Int, h: Int, min: Int, sec: Int): ZonedDateTime = - ZonedDateTime.of(LocalDate.of(y, month, d), LocalTime.of(h, min, sec), CalEvent.UTC) + ZonedDateTime.of(LocalDate.of(y, month, d), LocalTime.of(h, min, sec), ZoneOffset.UTC) }