Package: python-icron
IntroductionContentsIntroductionUsageAbout DSTAbout second supportGaps between date matchesIterating over a range using cronContributorsChangelog3.0.0 (2023-11-06)2.0.1 (2023-10-11)2.0.0 (2023-10-10)1.4.1 (2023-06-15)1.4.0 (2023-06-15)1.3.15 (2023-05-25)1.3.14 (2023-04-12)1.3.13 (2023-04-12)1.3.12 (2023-04-12)1.3.11 (2023-04-12)1.3.10 (2023-04-07)1.3.8 (2022-11-22)1.3.7 (2022-09-06)1.3.5 (2022-05-14)1.3.4 (2022-02-18)1.3.3 (2022-02-18)1.3.2 (2022-02-18)1.3.1 (2022-02-15)1.3.0 (2022-02-15)1.2.0 (2022-01-14)1.1.0 (2021-12-03)1.0.15 (2021-06-25)1.0.14 (2021-06-25)1.0.13 (2021-05-06)1.0.12 (2021-04-13)1.0.11 (2021-04-07)1.0.10 (2021-03-25)1.0.9 (2021-03-23)1.0.8 (2021-03-06)1.0.7 (2021-03-02)1.0.6 (2021-02-01)1.0.5 (2021-01-29)1.0.4 (2021-01-29)1.0.3 (2021-01-29)1.0.2 (2021-01-19)1.0.1 (2021-01-06)0.3.37 (2020-12-31)0.3.36 (2020-11-02)0.3.35 (2020-10-11)0.3.34 (2020-06-19)0.3.33 (2020-06-15)0.3.32 (2020-05-27)0.3.31 (2020-01-02)0.3.30 (2019-04-20)0.3.29 (2019-03-26)0.3.25 (2018-08-07)0.3.24 (2018-06-20)0.3.23 (2018-05-23)0.3.22 (2018-05-16)0.3.20 (2017-11-06)0.3.19 (2017-08-31)0.3.18 (2017-08-31)0.3.17 (2017-05-22)0.3.16 (2017-03-15)0.3.15 (2017-02-16)0.3.14 (2017-01-25)0.3.13 (2016-11-01)0.3.12 (2016-03-10)0.3.11 (2016-01-13)0.3.10 (2015-11-29)0.3.9 (2015-11-19)0.3.8 (2015-06-23)0.3.7 (2015-06-01)0.3.6 (2015-05-29)0.3.5 (2014-08-01)0.3.4 (2014-01-30)0.3.3 (2012-09-29)icronprovides iteration for the datetime object with a cron like format.
It is a fork of thecroniterpackages, with the following differences:full support for seconds (6 fields cron rules)removed support for random / jenkins style crons / hashed expressions._
(_) ___ _ __ ___  _ __
| |/ __| '__/ _ \| '_ \
| | (__| | | (_) | | | |
|_|\___|_|  \___/|_| |_|Website:https://hg.sr.ht/~pythonian/icronUsageA simple example:>>> from icron import croniter
>>> from datetime import datetime
>>> base = datetime(2010, 1, 25, 4, 46)
>>> iter = croniter('*/5 * * * *', base)  # every 5 minutes
>>> 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
>>>
>>> iter = croniter('2 4 * * mon,fri', base)  # 04:02 on every Monday and Friday
>>> print(iter.get_next(datetime))   # 2010-01-26 04:02:00
>>> print(iter.get_next(datetime))   # 2010-01-30 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-02 04:02:00
>>>
>>> iter = croniter('2 4 1 * wed', base)  # 04:02 on every Wednesday OR on 1st day of month
>>> print(iter.get_next(datetime))   # 2010-01-27 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-01 04:02:00
>>> print(iter.get_next(datetime))   # 2010-02-03 04:02:00
>>>
>>> iter = croniter('2 4 1 * wed', base, day_or=False)  # 04:02 on every 1st day of the month if it is a Wednesday
>>> print(iter.get_next(datetime))   # 2010-09-01 04:02:00
>>> print(iter.get_next(datetime))   # 2010-12-01 04:02:00
>>> print(iter.get_next(datetime))   # 2011-06-01 04:02:00
>>>
>>> iter = croniter('0 0 * * sat#1,sun#2', base)  # 1st Saturday, and 2nd Sunday of the month
>>> print(iter.get_next(datetime))   # 2010-02-06 00:00:00
>>>
>>> iter = croniter('0 0 * * 5#3,L5', base)  # 3rd and last Friday of the month
>>> print(iter.get_next(datetime))   # 2010-01-29 00:00:00
>>> print(iter.get_next(datetime))   # 2010-02-19 00:00:00All you need to know is how to use the constructor and theget_nextmethod, the signature of these methods are listed below:>>> def __init__(self, cron_format, start_time=time.time(), day_or=True)icron iterates along withcron_formatfromstart_time.cron_formatismin hour day month day_of_week, you can refer
tohttp://en.wikipedia.org/wiki/Cronfor more details. Theday_orswitch is used to control how croniter handlesdayandday_of_weekentries. Default option is the cron behaviour, which
connects those values usingOR. If the switch is set to False, the
values are connected usingAND. This behaves like fcron and
enables you to e.g. define a job that executes each 2nd Friday of a
month by setting the days of month and the weekday.>>> def get_next(self, ret_type=float)get_next calculates the next value according to the cron expression and
returns an object of typeret_type.ret_typeshould be afloator adatetimeobject.You can validate your crons usingis_validclass method. (>= 0.3.18):>>> croniter.is_valid('0 0 1 * *')  # True
>>> croniter.is_valid('0 wrong_value 1 * *')  # FalseAbout DSTBe sure to init your croniter instance with a TZ aware datetime for this to work!Example using pytz:>>> import pytz
>>> tz = pytz.timezone("Europe/Paris")
>>> local_date = tz.localize(datetime(2017, 3, 26))
>>> val = croniter('0 0 * * *', local_date).get_next(datetime)Example using python_dateutil:>>> import dateutil.tz
>>> tz = dateutil.tz.gettz('Asia/Tokyo')
>>> local_date = datetime(2017, 3, 26, tzinfo=tz)
>>> val = croniter('0 0 * * *', local_date).get_next(datetime)Example using python built in module:>>> from datetime import datetime, timezone
>>> local_date = datetime(2017, 3, 26, tzinfo=timezone.utc)
>>> val = croniter('0 0 * * *', local_date).get_next(datetime)About second supportIcron handles seconds just fine.Gaps between date matchesFor performance reasons, icron limits the amount of CPU cycles
spent attempting to find the next match.Starting in v0.3.35, this behavior is configurable via themax_years_between_matchesparameter, and the default window has
been increased from 1 year to 50 years.The defaults should be fine for many use cases.Applications that evaluate multiple cron expressions or handle cron
expressions from untrusted sources or end-users should use this
parameter.Iterating over sparse cron expressions can result in increased CPU
consumption or a raisedCroniterBadDateErrorexception which
indicates that croniter has given up attempting to find the next (or
previous) match.Explicitly specifyingmax_years_between_matchesprovides a way to
limit CPU utilization and simplifies the iterable interface by
eliminating the need forCroniterBadDateError.The difference in the iterable interface is based on the reasoning
that whenevermax_years_between_matchesis explicitly agreed upon,
there is no need for croniter to signal that it has given up; simply
stopping the iteration is preferable.This example matches 4 AM Friday, January 1st.Since January 1st isn’t often a Friday, there may be a few years
between each occurrence. Setting the limit to 15 years ensures all
matches:>>> it = croniter("0 4 1 1 fri", datetime(2000,1,1), day_or=False, max_years_between_matches=15).all_next(datetime)
>>> for i in range(5):
...     print(next(it))
...
2010-01-01 04:00:00
2016-01-01 04:00:00
2021-01-01 04:00:00
2027-01-01 04:00:00
2038-01-01 04:00:00However, when only concerned with dates within the next 5 years,
simply setmax_years_between_matches=5in the above example.This will result in no matches found, but no additional cycles will be
wasted on unwanted matches far in the future.Iterating over a range using cronFind matches within a range using thecroniter_range()function.
This is much like the builtinrange(start,stop,step)function, but
for dates.  Thestepargument is a cron expression.  Added in
(>=0.3.34)List the first Saturday of every month in 2019:>>> from icron import croniter_range
>>> for dt in croniter_range(datetime(2019, 1, 1), datetime(2019, 12, 31), "0 0 * * sat#1"):
>>>     print(dt)ContributorsThanks to all who have contributed to this project!
If you have contributed and your name is not listed below please let me know.Aurélien CampéasmrmachineHinnackshazowkiorkyjlsandellmag009djmitcheGreatCombinatorchris-baynesipartolayuzawa-sanlowell80 (Kintyre)scopzed2015Ryan Finnie (rfinnie)Changelog3.0.0 (2023-11-06)First release of icronRemoved non essential support code (jenkins, random, hashes)Added full seconds support (6 fields rule)Removed the “seconds repeat” feature2.0.1 (2023-10-11)Fix release issue [kiorky]2.0.0 (2023-10-10)Add Python 3.12 support [rafsaf]Make major release instructions [kiorky]1.4.1 (2023-06-15)Make a retrocompatible version of 1.4.0 change about supporting VIXIECRON bug. (fix #47)
[kiorky]1.4.0 (2023-06-15)Added “implement_cron_bug” flag to make the cron parser compatible with a bug in Vixie/ISC Cron
[kiorky, David White <dwhite2@cisco.com>]WARNING: EXPAND METHOD CHANGES RETURN VALUE1.3.15 (2023-05-25)Fix hashed expressions omitting some entries
[@waltervos/Walter Vos <walter.vos@ns.nl>]Enhance .match() precision for 6 position expressions
[@szpol/szymon <szymon.polinkiewicz@gmail.com>]1.3.14 (2023-04-12)Lint1.3.13 (2023-04-12)Add check for range begin/end1.3.12 (2023-04-12)restore py2 compat1.3.11 (2023-04-12)Do not exposeiinto global namespace1.3.10 (2023-04-07)Fix DOW hash parsing [kiorky]better error handling on py3 [kiorky]1.3.8 (2022-11-22)Add Python 3.11 support and move docs files to main folder [rafsaf]1.3.7 (2022-09-06)fix testsFix croniter_range infinite loop  [Shachar Snapiri <ssnapiri@paloaltonetworks.com>]1.3.5 (2022-05-14)Add Python 3.10 support [eelkevdbos]1.3.4 (2022-02-18)Really fix compat for tests under py27
[kiorky]1.3.3 (2022-02-18)Fix compat for tests under py27
[kiorky]1.3.2 (2022-02-18)Fix #12: regressions with set_current
[kiorky, agateblue]1.3.1 (2022-02-15)Restore compat with python2
[kiorky]1.3.0 (2022-02-15)Add a way to make next() easier to use. This fixes #11
[kiorky]1.2.0 (2022-01-14)Enforce validation for day=1. Before this release we used to support day=0 and it was silently glided to day=1 to support having both day in day in 4th field when it came to have 6fields cron forms (second repeat). It will now raises a CroniterBadDateError. Seehttps://github.com/kiorky/croniter/issues/6[kiorky]1.1.0 (2021-12-03)Enforce validation for month=1. Before this release we used to support month=0 and it was silently glided to month=1 to support having both day in month in 4th field when it came to have 6fields cron forms (second repeat). It will now raises a CroniterBadDateError. Seehttps://github.com/kiorky/croniter/issues/6[kiorky]1.0.15 (2021-06-25)restore py2 [kiorky]1.0.14 (2021-06-25)better type checks [kiorky]1.0.13 (2021-05-06)Fix ZeroDivisionError with* * R/0 * *[cuu508]1.0.12 (2021-04-13)Add support for hashed/random/keyword expressions
Ryan Finnie (rfinnie)Review support support for hashed/random/keyword expression and add expanders reactor
[ kiorky ]1.0.11 (2021-04-07)fix bug: bad case:0 6 30 3 *[zed2015(zhangchi)]Add support forLin the day_of_week component.  This enable expressions like* * * * L4, which means last Thursday of the month.  This resolves #159.
[Kintyre]CreateCroniterUnsupportedSyntaxErrorexception for situations where CRON syntax may be valid but some combinations of features is not supported.
Currently, this is used when theday_of_weekcomponent has a combination of literal values and nth/last syntax at the same time.
For example,0 0 * * 1,L6or0 0 * * 15,sat#1will both raise this exception because of mixing literal days of the week with nth-weekday or last-weekday syntax.
Thismayimpact existing cron expressions in prior releases, because0 0 * * 15,sat#1was previously allowed but incorrectly handled.
[Kintyre]Updatecroniter_range()to allow an alternatecroniterclass to be used.  Helpful when using a custom class derived from croniter.
[Kintyre]1.0.10 (2021-03-25)Remove external librarynatsort.
Sorting of cron expression components now handled withsorted()with a customkeyfunction.
[Kintyre]1.0.9 (2021-03-23)Remove futures dependency
[kiorky]1.0.8 (2021-03-06)Update_expandto lowercase each component of the expression.
This is in relation to #157. With this change, croniter accepts and correctly handles* * 10-L * *.
[cuu508]1.0.7 (2021-03-02)Fix _expand to reject int literals with underscores
[cuu508]Remove a debug statement to make flake8 happy
[cuu508]1.0.6 (2021-02-01)Fix combination of star and invalid expression bugs
[kiorky]1.0.5 (2021-01-29)Security fix: fix overflow when using cron ranges
[kiorky]1.0.4 (2021-01-29)Spelling fix release1.0.3 (2021-01-29)Fix #155: raise CroniterBadCronError when error syntax
[kiorky]1.0.2 (2021-01-19)Fix match when datetime has microseconds
[kiorky]1.0.1 (2021-01-06)no changes, just to make sense with new semver2 (making croniter on a stable state)
[kiorky]0.3.37 (2020-12-31)Added Python 3.8 and 3.9 support
[eumiro]0.3.36 (2020-11-02)Updated docs section regardingmax_years_between_matchesto be more shorter and hopefully more relevant.
[Kintyre]Don’t install tests
[scop]0.3.35 (2020-10-11)Handle L in ranges. This fixes #142.
[kiorky]Add a new initialization parametermax_years_between_matchesto support finding the next/previous date beyond the default 1 year window, if so desired.  Updated README to include additional notes and example of this usage.  Fixes #145.
[Kintyre]Thecroniter_range()function was updated to automatically determines the appropriatemax_years_between_matchesvalue, this preventing handling of theCroniterBadDateErrorexception.
[Kintyre]Updated exception handling classes:CroniterBadDateErrornow only
applies during date finding operations (next/prev), and all parsing errors can now be caught usingCroniterBadCronError.  TheCroniterNotAlphaErrorexception is now a subclass ofCroniterBadCronError.  A brief description of each exception class was added as an inline docstring.
[Kintyre]Updated iterable interfaces to replace theCroniterBadDateErrorwithStopIterationif (and only if) themax_years_between_matchesargument is provided.  The rationale here is that if the user has specified the max tolerance between matches, then there’s no need to further inform them of no additional matches.  Just stop the iteration.  This also keeps backwards compatibility.
[Kintyre]Minor docs update
[Kintyre]0.3.34 (2020-06-19)Featcroniter_range(start, stop, cron)[Kintyre]Optimization for poorly written cron expression
[Kintyre]0.3.33 (2020-06-15)Make dateutil tz support more official
[Kintyre]Feat/support for day or
[田口信元]0.3.32 (2020-05-27)document seconds repeats, fixes #122
[kiorky]Implement match method, fixes #54
[kiorky]Adding tests for #127 (test more DSTs and croniter behavior around)
[kiorky]Changed lag_hours comparison to absolute to manage dst boundary when getting previous
[Sokkka]0.3.31 (2020-01-02)Fix get_next() when start_time less then 1s before next instant
[AlexHill]0.3.30 (2019-04-20)credits0.3.29 (2019-03-26)creditshistory stripping (security)Handle -Sun notation, This fixes#119.
[kiorky]Handle invalid ranges correctly,  This fixes#114.
[kiorky]0.3.25 (2018-08-07)Pypi hygiene
[hugovk]0.3.24 (2018-06-20)fix#107: microsecond threshold
[kiorky]0.3.23 (2018-05-23)fixget_nextwhile preserving the fix ofget_previn 7661c2aaa
[Avikam Agur <avikam@pagaya-inv.com>]0.3.22 (2018-05-16)Don’t count previous minute if now is dynamic
If the code is triggered from 5-asterisk based cronget_prevbased ondatetime.now()is expected to return
current cron iteration and not previous execution.
[Igor Khrol <igor.khrol@toptal.com>]0.3.20 (2017-11-06)More DST fixes
[Kevin Rose <kbrose@github>]0.3.19 (2017-08-31)fix #87: backward dst changes
[kiorky]0.3.18 (2017-08-31)Add is valid method, refactor errors
[otherpirate, Mauro Murari <mauro_murari@hotmail.com>]0.3.17 (2017-05-22)DOW occurrence sharp style support.
[kiorky, Kengo Seki <sekikn@apache.org>]0.3.16 (2017-03-15)Better test suite [mrcrilly@github]DST support [kiorky]0.3.15 (2017-02-16)fix bug around multiple conditions and range_val in
_get_prev_nearest_diff.
[abeja-yuki@github]0.3.14 (2017-01-25)issue #69: added day_or option to change behavior when day-of-month and
day-of-week is given
[Andreas Vogl <a.vogl@hackner-security.com>]0.3.13 (2016-11-01)Real fix for #34[kiorky@github]Modernize test infra[kiorky@github]Release as a universal wheel[adamchainz@github]Raise ValueError on negative numbers[josegonzalez@github]Compare types using “issubclass” instead of exact match[darkk@github]Implement step cron with a variable base[josegonzalez@github]0.3.12 (2016-03-10)support setting ret_type in __init__ [Brent Tubbs <brent.tubbs@gmail.com>]0.3.11 (2016-01-13)Bug fix: The get_prev API crashed when last day of month token was used. Some
essential logic was missing.
[Iddo Aviram <iddo.aviram@similarweb.com>]0.3.10 (2015-11-29)The functionality of ‘l’ as day of month was broken, since the month variable
was not properly updated
[Iddo Aviram <iddo.aviram@similarweb.com>]0.3.9 (2015-11-19)Don’t use datetime functions python 2.6 doesn’t support
[petervtzand]0.3.8 (2015-06-23)Truncate microseconds by setting to 0
[Corey Wright]0.3.7 (2015-06-01)converting sun in range sun-thu transforms to int 0 which is
recognized as empty string; the solution was to convert sun to string “0”0.3.6 (2015-05-29)Fix default behavior when no start_time given
Default value forstart_timeparameter is calculated at module init time rather than call time.Fix timezone support and stop depending on the system time zone0.3.5 (2014-08-01)support for ‘l’ (last day of month)0.3.4 (2014-01-30)Python 3 compatQA Release0.3.3 (2012-09-29)proper packaging