def test_nonexistent_days(timezone: DstTzInfo):
    """Test that invalid dates are skipped."""
    schedule = CalendarIntervalSchedule(task_id='task', timezone=timezone, months=1,
                                        start_date=date(2016, 3, 31))

    now = timezone.localize(datetime(2016, 4, 30))
    expected = timezone.localize(datetime(2016, 5, 31))
    assert schedule.get_next_run_time(now) == expected
def test_missing_time(timezone: DstTzInfo):
    """
    Test that if the designated time does not exist on a day due to a forward DST shift, the day is
    skipped entirely.

    """
    schedule = CalendarIntervalSchedule(task_id='task', timezone=timezone, days=1, hour=2,
                                        minute=30, start_date=date(2016, 3, 27))
    now = timezone.localize(datetime(2016, 3, 27))
    expected = timezone.localize(datetime(2016, 3, 28, 2, 30))
    assert schedule.get_next_run_time(now) == expected
def test_repeated_time(timezone: DstTzInfo):
    """
    Test that if the designated time is repeated during a day due to a backward DST shift, the task
    is executed twice that day.

    """
    schedule = CalendarIntervalSchedule(task_id='task', timezone=timezone, days=2, hour=2,
                                        minute=30, start_date=date(2016, 10, 30))

    # The first returned datetime should be the on still in DST
    now = timezone.localize(datetime(2016, 10, 30))
    expected = timezone.localize(datetime(2016, 10, 30, 2, 30), is_dst=True)
    assert schedule.get_next_run_time(now) == expected

    # The next one should then be the one w/o DST
    now = timezone.localize(datetime(2016, 10, 30, 2, 40), is_dst=True)
    expected = timezone.localize(datetime(2016, 10, 30, 2, 30), is_dst=False)
    assert schedule.get_next_run_time(now) == expected

    # But if both times have passed, move on to the next interval
    now = timezone.localize(datetime(2016, 10, 30, 2, 40), is_dst=False)
    expected = timezone.localize(datetime(2016, 11, 1, 2, 30))
    assert schedule.get_next_run_time(now) == expected
def test_end_date(schedule: CalendarIntervalSchedule, timezone: DstTzInfo):
    """Test that end_date is respected."""
    now = timezone.localize(datetime(2020, 12, 31))
    assert schedule.get_next_run_time(now) is None
def test_start_date(schedule: CalendarIntervalSchedule, timezone: DstTzInfo):
    """Test that start_date is respected."""
    now = timezone.localize(datetime(2016, 1, 15))
    expected = timezone.localize(datetime(2016, 3, 5, 3, 0, 8))
    assert schedule.get_next_run_time(now) == expected