MonthlyTrigger implements Trigger { @Override public ZonedDateTime next(ZonedDateTime previous) { ZonedDateTime next = previous.withDayOfMonth(dayOfMonth).with(time); if (!next.isAfter(previous)) { next = next.plusMonths(1).with(time); } return next; } MonthlyTrigger(int dayOfMonth, LocalTime time); @Override ZonedDateTime next(ZonedDateTime previous); @Override String toString();  }
@Test void next() { MonthlyTrigger trigger = new MonthlyTrigger(2, LocalTime.of(3, 0)); assertThat(trigger.next(date("2017-04-02T02:00:00"))).isEqualTo(date("2017-04-02T03:00:00")); assertThat(trigger.next(ZonedDateTime.parse("2017-04-02T02:00:00Z"))).isEqualTo("2017-04-02T03:00:00Z"); assertThat(trigger.next(date("2017-04-02T03:00:00"))).isEqualTo(date("2017-05-02T03:00:00")); assertThat(trigger.next(date("2017-04-02T03:30:00"))).isEqualTo(date("2017-05-02T03:00:00")); }