croniter provides iteration for datetime object with cron like format
npx @tessl/cli install tessl/pypi-croniter@6.0.0Croniter provides iteration for datetime objects with a cron-like format. It enables developers to calculate next and previous execution times based on cron expressions, supports advanced cron features including second-level precision, year fields, timezone-aware calculations, and Jenkins-style hashed expressions. The library offers comprehensive cron validation, range matching, and supports various cron extensions like @yearly, @monthly shortcuts.
pip install croniterfrom croniter import croniterFor range operations:
from croniter import croniter_rangeFor validation and matching:
from croniter import croniterComplete import with exceptions and constants:
from croniter import (
croniter,
croniter_range,
datetime_to_timestamp,
# Field constants
MINUTE_FIELD,
HOUR_FIELD,
DAY_FIELD,
MONTH_FIELD,
SECOND_FIELD,
YEAR_FIELD,
OVERFLOW32B_MODE,
UTC_DT,
# Exception classes
CroniterError,
CroniterBadCronError,
CroniterBadDateError,
CroniterBadTypeRangeError,
CroniterNotAlphaError,
CroniterUnsupportedSyntaxError
)from croniter import croniter
from datetime import datetime
# Create a croniter instance for every 5 minutes
base = datetime(2010, 1, 25, 4, 46)
iter = croniter('*/5 * * * *', base)
# Get next execution times
print(iter.get_next(datetime)) # 2010-01-25 04:50:00
print(iter.get_next(datetime)) # 2010-01-25 04:55:00
print(iter.get_next(datetime)) # 2010-01-25 05:00:00
# Work with more complex expressions
iter = croniter('2 4 * * mon,fri', base) # 04:02 on Monday and Friday
print(iter.get_next(datetime)) # 2010-01-26 04:02:00
print(iter.get_next(datetime)) # 2010-01-30 04:02:00Croniter is built around the core croniter class which parses cron expressions and provides iteration capabilities. The library supports:
Key components include:
Main croniter class providing datetime iteration based on cron expressions, with support for both forward and backward iteration, timezone handling, and various cron formats.
class croniter:
def __init__(
self,
expr_format: str,
start_time=None,
ret_type=float,
day_or=True,
max_years_between_matches=None,
is_prev=False,
hash_id=None,
implement_cron_bug=False,
second_at_beginning=None,
expand_from_start_time=False,
): ...
def get_next(self, ret_type=None, start_time=None, update_current=True): ...
def get_prev(self, ret_type=None, start_time=None, update_current=True): ...Range-based iteration functionality similar to Python's built-in range() function, but for datetime objects using cron expressions as the "step" parameter.
def croniter_range(
start,
stop,
expr_format: str,
ret_type=None,
day_or=True,
exclude_ends=False,
_croniter=None,
second_at_beginning=False,
expand_from_start_time=False,
): ...Comprehensive validation of cron expressions and testing whether specific datetime objects match cron patterns, including range-based matching.
@classmethod
def is_valid(
cls,
expression: str,
hash_id=None,
encoding="UTF-8",
second_at_beginning=False,
) -> bool: ...
@classmethod
def match(cls, cron_expression: str, testdate, day_or=True, second_at_beginning=False) -> bool: ...
@classmethod
def match_range(
cls,
cron_expression: str,
from_datetime,
to_datetime,
day_or=True,
second_at_beginning=False,
) -> bool: ...Advanced croniter features including Jenkins-style hashed expressions, random expressions, custom start time expansion, and specialized cron syntax support.
# Hashed expressions
iter = croniter("H H * * *", hash_id="unique-job-id")
# Random expressions
iter = croniter("R R * * *")
# Custom expansion from start time
iter = croniter('0 0 */7 * *', start_time=datetime(2024, 7, 11), expand_from_start_time=True)class CroniterError(ValueError):
"""General top-level Croniter base exception"""
class CroniterBadCronError(CroniterError):
"""Syntax, unknown value, or range error within a cron expression"""
class CroniterBadDateError(CroniterError):
"""Unable to find next/prev timestamp match"""
class CroniterBadTypeRangeError(TypeError):
"""Type error for range operations"""
class CroniterNotAlphaError(CroniterBadCronError):
"""Cron syntax contains an invalid day or month abbreviation"""
class CroniterUnsupportedSyntaxError(CroniterBadCronError):
"""Valid cron syntax, but likely to produce inaccurate results"""MINUTE_FIELD: int = 0
HOUR_FIELD: int = 1
DAY_FIELD: int = 2
MONTH_FIELD: int = 3
DOW_FIELD: int = 4 # Day of week field
SECOND_FIELD: int = 5
YEAR_FIELD: int = 6
OVERFLOW32B_MODE: bool # 32-bit overflow detection flag
UTC_DT # UTC timezone object
# Field tuple constants for different cron formats
UNIX_FIELDS: tuple # (MINUTE_FIELD, HOUR_FIELD, DAY_FIELD, MONTH_FIELD, DOW_FIELD)
SECOND_FIELDS: tuple # (MINUTE_FIELD, HOUR_FIELD, DAY_FIELD, MONTH_FIELD, DOW_FIELD, SECOND_FIELD)
YEAR_FIELDS: tuple # (MINUTE_FIELD, HOUR_FIELD, DAY_FIELD, MONTH_FIELD, DOW_FIELD, SECOND_FIELD, YEAR_FIELD)
# Cron expression length constants
UNIX_CRON_LEN: int = 5 # Standard 5-field cron format
SECOND_CRON_LEN: int = 6 # 6-field cron format with seconds
YEAR_CRON_LEN: int = 7 # 7-field cron format with seconds and yeardef datetime_to_timestamp(d) -> float:
"""Convert datetime object to UNIX timestamp"""