{"id":473,"library":"croniter","title":"croniter","description":"croniter is a Python library that provides iteration capabilities for `datetime` objects based on cron-like formats. It allows generating future or past occurrences matching a given cron expression. The current version is 6.2.2, released on March 15, 2026. While it experienced a period of abandonment, it is now actively maintained by the Pallets-Eco organization.","status":"active","version":"6.2.2","language":"python","source_language":"en","source_url":"https://github.com/pallets-eco/croniter","tags":["cron","scheduling","datetime","iteration","time"],"install":[{"cmd":"pip install croniter","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Required for date and time parsing and manipulation.","package":"python-dateutil","optional":false},{"reason":"Recommended for handling timezones, especially with older versions or complex DST scenarios.","package":"pytz","optional":true}],"imports":[{"symbol":"croniter","correct":"from croniter import croniter"}],"quickstart":{"code":"from datetime import datetime\nfrom croniter import croniter\n\n# Example 1: Every 5 minutes\nbase = datetime(2010, 1, 25, 4, 46)\niter_5min = croniter('*/5 * * * *', base)\nprint(f\"Next occurrence (every 5 min): {iter_5min.get_next(datetime)}\")\n\n# Example 2: Every Monday and Friday at 04:02\nbase = datetime.now()\niter_mf = croniter('2 4 * * mon,fri', base)\nprint(f\"Next occurrence (Mon/Fri 04:02): {iter_mf.get_next(datetime)}\")\n\n# Example 3: First day of the month AND a Wednesday\n# (using day_or=False for AND logic, like fcron)\nbase = datetime.now()\niter_and = croniter('2 4 1 * wed', base, day_or=False)\nprint(f\"Next occurrence (1st day AND Wed 04:02): {iter_and.get_next(datetime)}\")","lang":"python","description":"Demonstrates creating a croniter object and retrieving the next matching datetime. It also shows the `day_or` parameter for 'AND' logic between day-of-month and day-of-week fields."},"warnings":[{"fix":"Ensure installation from the official PyPI `croniter` package, which is now maintained by Pallets-Eco, and update to the latest version (6.x.x) if using an older, unmaintained fork.","message":"The `croniter` project was previously declared unmaintained and abandoned by its original author in late 2024 due to concerns about the EU Cyber Resilience Act. It has since been adopted and is now maintained by Pallets-Eco. Users should ensure they are using the `pallets-eco` version and monitor its status if the CRA impacts open source libraries.","severity":"breaking","affected_versions":"<= 6.0.0 (original author's branch)"},{"fix":"If 'AND' logic is desired for day and day-of-week fields, initialize `croniter` with `croniter(cron_expression, base, day_or=False)`.","message":"By default, `croniter` uses 'OR' logic when both 'day of month' and 'day of week' fields are specified in a cron expression, matching standard Vixie-cron behavior. This means a schedule will trigger if *either* the day of month *or* the day of week matches. For 'AND' logic (trigger only if *both* match, like fcron), you must explicitly pass `day_or=False` to the `croniter` constructor.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Carefully review cron expressions, especially those with reverse ranges. Validate the generated iterations against expected behavior, or use a more strictly validated cron string if precise adherence to a specific cron flavor is critical.","message":"`croniter` is less strict than some cron implementations regarding ranges for months (e.g., 'APR-JAN') and days of the week (e.g., 'SAT-SUN', 'WED-SUN'). These reverse ranges are interpreted, which might lead to unexpected iterations if a strict cron parser is anticipated.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use `croniter.is_valid(cron_expression, strict=True)` for comprehensive validation, especially with user-provided cron strings, to prevent parsing impossible dates.","message":"The `is_valid()` method, by default, only performs basic syntax and field range validation. It does not perform cross-field validation (e.g., it will report '31 2 * * *' as valid even though February has no 31st). To enable strict cross-field validation, you must pass `strict=True`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"When using `croniter.match()`, be aware of its default precision. For highly precise matching, consider comparing `datetime` objects directly or adjusting the comparison logic.","message":"The `croniter.match()` method has a default precision of 60 seconds for 5-field expressions and 1 second for 6-field expressions. This means a target `datetime` up to 60 (or 1) seconds *after* the scheduled time will still be considered a match. This can cause issues in scenarios requiring exact time matching.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T14:05:18.254Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Install the croniter package using pip: `pip install croniter`","cause":"The 'croniter' library is not installed in the Python environment where the code is being executed.","error":"ModuleNotFoundError: No module named 'croniter'"},{"fix":"Ensure your cron expression has either 5 or 6 space-separated fields. For example, '0 0 * * *' for daily at midnight, or '0 0 0 * * *' for daily at midnight with seconds.","cause":"The provided cron expression string is malformed and does not contain the required 5 fields (minute, hour, day of month, month, day of week) or 6 fields (including seconds).","error":"croniter.croniter.CroniterBadCronError: Exactly 5 or 6 columns has to be specified for iterator expression."},{"fix":"Carefully review the cron expression for any invalid characters, out-of-range numbers, or incorrect syntax. Use `croniter.is_valid(cron_expression)` for pre-validation or consult cron syntax documentation.","cause":"This generic error can be raised by `croniter` for various reasons, such as providing an invalid character in a cron field, specifying a number outside the valid range for a field (e.g., month 13), or using an invalid cron step (e.g., '0-10/error').","error":"ValueError"},{"fix":"For very sparse cron expressions, consider increasing the `max_years_between_matches` parameter in the `croniter` constructor (e.g., `croniter(cron_expression, base, max_years_between_matches=200)`). Alternatively, ensure the cron expression is feasible given the `base` datetime.","cause":"The `croniter` library could not find a matching next (or previous) date for the given cron expression within its default search window (typically 50 years). This often happens with very sparse or impossible cron expressions, like '0 0 29 2 *' when the `base` date is in a non-leap year and the next valid date is too far in the future.","error":"croniter.croniter.CroniterBadDateError: failed to find next date"},{"fix":"Ensure that the `ret_type` argument, if provided, is either `float` or `datetime.datetime`. For example: `iter.get_next(datetime.datetime)` or `iter.get_next(float)`.","cause":"When calling methods like `get_next()` or `get_prev()`, an invalid type was passed to the `ret_type` argument. `croniter` expects either `float` or `datetime.datetime`.","error":"TypeError: Invalid ret_type, only 'float' or 'datetime'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":2.3,"disk_size":"19.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":2.3,"disk_size":"20M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":2.6,"disk_size":"21.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":2.6,"disk_size":"22M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.5,"disk_size":"13.0M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.5,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.6,"disk_size":"12.6M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.4,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2.3,"disk_size":"18.5M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2.3,"disk_size":"19M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}