Ejemplo n.º 1
0
 def test_hash_id_change(self):
     """Test a different hash_id returns different results given same definition and epoch"""
     obj = croniter_hash("H H * * *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 1, 11, 10))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 11, 10) + timedelta(days=1))
     obj = croniter_hash("H H * * *", self.epoch, hash_id="different id")
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 1, 0, 24))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 0, 24) + timedelta(days=1))
Ejemplo n.º 2
0
    def test_hash_word_annually(self):
        """Test built-in @annually

        @annually is the same as @yearly
        """
        obj_annually = croniter_hash("@annually",
                                     self.epoch,
                                     hash_id=self.hash_id)
        obj_yearly = croniter_hash("@yearly", self.epoch, hash_id=self.hash_id)
        self.assertEqual(obj_annually.get_next(datetime),
                         obj_yearly.get_next(datetime))
Ejemplo n.º 3
0
 def test_hash_word_daily(self):
     """Test built-in @daily"""
     obj = croniter_hash("@daily", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 11, 10, 32))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 11, 10, 32) + timedelta(days=1))
Ejemplo n.º 4
0
 def test_hash_id_bytes(self):
     """Test hash_id as a bytes object"""
     obj = croniter_hash("H H * * *",
                         self.epoch,
                         hash_id=b"\x01\x02\x03\x04")
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 1, 14, 53))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 14, 53) + timedelta(days=1))
Ejemplo n.º 5
0
 def test_random_float(self):
     """Test random definition, float result"""
     obj = croniter_hash("R R * * *", self.epoch, hash_id=self.hash_id)
     result_1 = obj.get_next(float)
     self.assertGreaterEqual(result_1, 1577836800.0)
     self.assertLessEqual(result_1, 1577836800.0 + (60 * 60 * 24))
     result_2 = obj.get_next(float)
     self.assertGreaterEqual(result_2, 1577923200.0)
     self.assertLessEqual(result_2, 1577923200.0 + (60 * 60 * 24))
Ejemplo n.º 6
0
    def test_hash_word_midnight(self):
        """Test built-in @midnight

        @midnight is actually up to 3 hours after midnight, not exactly midnight
        """
        obj = croniter_hash("@midnight", self.epoch, hash_id=self.hash_id)
        self.assertEqual(obj.get_next(datetime),
                         datetime(2020, 1, 1, 2, 10, 32))
        self.assertEqual(obj.get_next(datetime),
                         datetime(2020, 1, 1, 2, 10, 32) + timedelta(days=1))
Ejemplo n.º 7
0
    def test_hash_second(self):
        """Test seconds

        If a sixth field is provided, seconds are included in the datetime()
        """
        obj = croniter_hash("H H * * * H", self.epoch, hash_id=self.hash_id)
        self.assertEqual(obj.get_next(datetime),
                         datetime(2020, 1, 1, 11, 10, 32))
        self.assertEqual(obj.get_next(datetime),
                         datetime(2020, 1, 1, 11, 10, 32) + timedelta(days=1))
Ejemplo n.º 8
0
 def test_hash_weekly(self):
     """Test manually-defined weekly"""
     obj = croniter_hash("H H * * H", self.epoch, hash_id=self.hash_id)
     testval = obj.get_next(datetime)
     # croniter 1.0.5 changes the defined weekly range from (0, 6)
     # to (0, 7), to match cron's behavior that Sunday is 0 or 7.
     # This changes our hash, so test for either.
     self.assertIn(
         testval,
         (datetime(2020, 1, 3, 11, 10), datetime(2020, 1, 5, 11, 10)))
     self.assertEqual(obj.get_next(datetime), testval + timedelta(weeks=1))
Ejemplo n.º 9
0
 def test_random(self):
     """Test random definition"""
     obj = croniter_hash("R R * * *", self.epoch, hash_id=self.hash_id)
     result_1 = obj.get_next(datetime)
     self.assertGreaterEqual(result_1, datetime(2020, 1, 1, 0, 0))
     self.assertLessEqual(result_1,
                          datetime(2020, 1, 1, 0, 0) + timedelta(days=1))
     result_2 = obj.get_next(datetime)
     self.assertGreaterEqual(result_2, datetime(2020, 1, 2, 0, 0))
     self.assertLessEqual(result_2,
                          datetime(2020, 1, 2, 0, 0) + timedelta(days=1))
Ejemplo n.º 10
0
 def test_random_range(self):
     """Test random definition within a range"""
     obj = croniter_hash("R R R(10-20) * *",
                         self.epoch,
                         hash_id=self.hash_id)
     result_1 = obj.get_next(datetime)
     self.assertGreaterEqual(result_1, datetime(2020, 1, 10, 0, 0))
     self.assertLessEqual(result_1,
                          datetime(2020, 1, 10, 0, 0) + timedelta(days=11))
     result_2 = obj.get_next(datetime)
     self.assertGreaterEqual(result_2, datetime(2020, 2, 10, 0, 0))
     self.assertLessEqual(result_2,
                          datetime(2020, 2, 10, 0, 0) + timedelta(days=11))
Ejemplo n.º 11
0
def frequency_next_scheduled(frequency, source_id, base_time=None):
    """Return the next scheduled datetime, given a frequency definition

    Examples of English definitions:
        "hourly", "daily", "weekly", "sunday", "monday", "tuesday",
        "wednesday", "thursday", "friday", "saturday"
    Within a specific time range: "daily, 0800-1600"
    These definitions will return a randomly-hashed time within the
    definition each time.

    If croniter is installed, "cron" plus a cron definition can be used:
        "cron 42 8 * * *"
    Or a Jenkins-style hashed cron definition, consistently hashed
    against the source ID:
        "cron H H(8-16) * * *"
    Or randomized:
        "cron R R(8-16) * * *"
    """
    if not base_time:
        base_time = timezone.now()

    if frequency.startswith("cron"):
        if isinstance(croniter_hash, ImportError):
            # croniter is not installed
            raise croniter_hash
        cron_schedule = " ".join(frequency.split(" ")[1:])
        croniter_def = croniter_hash(cron_schedule,
                                     start_time=base_time,
                                     hash_id=source_id)
        return croniter_def.get_next(datetime).replace(
            second=hashedint(0, 59, source_id))

    f = [x.strip() for x in frequency.split(",")]

    if f[0] == "hourly":
        target_time = (base_time.replace(
            minute=hashedint(0, 59, source_id),
            second=hashedint(0, 59, source_id),
            microsecond=0,
        ) + timedelta(hours=1))
        return target_time

    today = base_time.replace(hour=0, minute=0, second=0, microsecond=0)
    if f[0] == "daily":
        # Tomorrow
        target_date = today + timedelta(days=1)
    elif f[0] == "weekly":
        # Hashed day next week
        target_day = hashedint(0, 6, source_id)
        target_date = (today + timedelta(weeks=1) -
                       timedelta(days=((today.weekday() + 1) % 7)) +
                       timedelta(days=target_day))
    elif f[0] in (
            "sunday",
            "monday",
            "tuesday",
            "wednesday",
            "thursday",
            "friday",
            "saturday",
    ):
        # Next Xday
        day_map = {
            "sunday": 0,
            "monday": 1,
            "tuesday": 2,
            "wednesday": 3,
            "thursday": 4,
            "friday": 5,
            "saturday": 6,
        }
        target_day = day_map[f[0]]
        target_date = (today - timedelta(days=((today.weekday() + 1) % 7)) +
                       timedelta(days=target_day))
        if target_date < today:
            target_date = target_date + timedelta(weeks=1)
    elif f[0] == "monthly":
        next_month = (today.replace(day=1) + timedelta(days=40)).replace(day=1)
        month_after = (next_month.replace(day=1) +
                       timedelta(days=40)).replace(day=1)
        target_date = next_month + timedelta(
            days=hashedint(1, (month_after - next_month).days, source_id))
    else:
        # Fall back to daily
        target_date = today + timedelta(days=1)

    if len(f) == 1:
        return target_date + timedelta(seconds=hashedint(0, 86399, source_id))
    time_range = f[1].split("-")
    start = (int(time_range[0][0:2]) * 60 * 60) + (int(time_range[0][2:4]) *
                                                   60)
    if len(time_range) == 1:
        # Not a range
        return target_date + timedelta(seconds=start)
    end = (int(time_range[1][0:2]) * 60 * 60) + (int(time_range[1][2:4]) * 60)
    if end < start:
        # Day rollover
        end = end + 86400
    return target_date + timedelta(seconds=hashedint(start, end, source_id))
Ejemplo n.º 12
0
 def test_hash_range(self):
     """Test a hashed range definition"""
     obj = croniter_hash("H H H(3-5) * *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 5, 11, 10))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 5, 11, 10) + timedelta(days=31))
Ejemplo n.º 13
0
 def test_hash_yearly(self):
     """Test manually-defined yearly"""
     obj = croniter_hash("H H H H *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime), datetime(2020, 9, 1, 11, 10))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 9, 1, 11, 10) + timedelta(days=365))
Ejemplo n.º 14
0
 def test_invalid_hash_id_type(self):
     """Test an invalid hash_id type raises TypeError"""
     with self.assertRaises(TypeError):
         croniter_hash("H H * * *", self.epoch, hash_id={1: 2})
Ejemplo n.º 15
0
 def test_invalid_get_next_type(self):
     """Test an invalid get_next type raises TypeError"""
     obj = croniter_hash("H H * * *", self.epoch, hash_id=self.hash_id)
     with self.assertRaises(TypeError):
         obj.get_next(str)
Ejemplo n.º 16
0
 def test_invalid_definition(self):
     """Test an invalid defition raises CroniterNotAlphaError"""
     with self.assertRaises(croniter.CroniterNotAlphaError):
         croniter_hash("X X * * *", self.epoch, hash_id=self.hash_id)
Ejemplo n.º 17
0
 def test_cron(self):
     """Test standard croniter functionality"""
     obj = croniter_hash("35 6 * * *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 1, 6, 35))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 6, 35) + timedelta(days=1))
Ejemplo n.º 18
0
 def test_hash_float(self):
     """Test result as a float object"""
     obj = croniter_hash("H H * * *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(float), 1577877000.0)
     self.assertEqual(obj.get_next(float), 1577877000.0 + (60 * 60 * 24))
Ejemplo n.º 19
0
 def test_hash_hourly(self):
     """Test manually-defined hourly"""
     obj = croniter_hash("H * * * *", self.epoch, hash_id=self.hash_id)
     self.assertEqual(obj.get_next(datetime), datetime(2020, 1, 1, 0, 10))
     self.assertEqual(obj.get_next(datetime),
                      datetime(2020, 1, 1, 0, 10) + timedelta(hours=1))