METADATA 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. Metadata-Version: 2.1
  2. Name: croniter
  3. Version: 6.0.0
  4. Summary: croniter provides iteration for datetime object with cron like format
  5. Home-page: http://github.com/kiorky/croniter
  6. Author: Matsumoto Taichi, kiorky
  7. Author-email: taichino@gmail.com, kiorky@cryptelium.net
  8. License: MIT License
  9. Keywords: datetime,iterator,cron
  10. Classifier: Development Status :: 4 - Beta
  11. Classifier: Intended Audience :: Developers
  12. Classifier: License :: OSI Approved :: MIT License
  13. Classifier: Operating System :: POSIX
  14. Classifier: Programming Language :: Python
  15. Classifier: Programming Language :: Python :: 2
  16. Classifier: Programming Language :: Python :: 2.6
  17. Classifier: Programming Language :: Python :: 2.7
  18. Classifier: Programming Language :: Python :: 3
  19. Classifier: Programming Language :: Python :: 3.4
  20. Classifier: Programming Language :: Python :: 3.5
  21. Classifier: Programming Language :: Python :: 3.6
  22. Classifier: Programming Language :: Python :: 3.7
  23. Classifier: Programming Language :: Python :: 3.8
  24. Classifier: Programming Language :: Python :: 3.9
  25. Classifier: Programming Language :: Python :: 3.10
  26. Classifier: Programming Language :: Python :: 3.11
  27. Classifier: Programming Language :: Python :: 3.12
  28. Classifier: Programming Language :: Python :: 3.13
  29. Classifier: Topic :: Software Development :: Libraries :: Python Modules
  30. Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
  31. License-File: LICENSE
  32. Requires-Dist: python-dateutil
  33. Requires-Dist: pytz>2021.1
  34. Introduction
  35. ============
  36. DISCLAIMER
  37. ============
  38. **UNMAINTAINED/ABANDONED CODE / DO NOT USE**
  39. Due to the new EU Cyber Resilience Act (as European Union), even if it was implied because there was no more activity, this repository is now explicitly declared unmaintained.
  40. The content does not meet the new regulatory requirements and therefore cannot be deployed or distributed, especially in a European context.
  41. This repository now remains online ONLY for public archiving, documentation and education purposes and we ask everyone to respect this.
  42. As stated, the maintainers stopped development and therefore all support some time ago, and make this declaration on December 15, 2024.
  43. We may also unpublish soon (as in the following monthes) any published ressources tied to this project (pypi, the repositories, ...).
  44. So, please don't rely on it after March 15, 2025 and adapt whatever project which used this code.
  45. .. contents::
  46. croniter provides iteration for the datetime object with a cron like format.
  47. ::
  48. _ _
  49. ___ _ __ ___ _ __ (_) |_ ___ _ __
  50. / __| '__/ _ \| '_ \| | __/ _ \ '__|
  51. | (__| | | (_) | | | | | || __/ |
  52. \___|_| \___/|_| |_|_|\__\___|_|
  53. Website: https://github.com/kiorky/croniter
  54. Build Badge
  55. ===========
  56. .. image:: https://github.com/kiorky/croniter/actions/workflows/cicd.yml/badge.svg
  57. :target: https://github.com/kiorky/croniter/actions/workflows/cicd.yml
  58. Usage
  59. ============
  60. A simple example::
  61. >>> from croniter import croniter
  62. >>> from datetime import datetime
  63. >>> base = datetime(2010, 1, 25, 4, 46)
  64. >>> iter = croniter('*/5 * * * *', base) # every 5 minutes
  65. >>> print(iter.get_next(datetime)) # 2010-01-25 04:50:00
  66. >>> print(iter.get_next(datetime)) # 2010-01-25 04:55:00
  67. >>> print(iter.get_next(datetime)) # 2010-01-25 05:00:00
  68. >>>
  69. >>> iter = croniter('2 4 * * mon,fri', base) # 04:02 on every Monday and Friday
  70. >>> print(iter.get_next(datetime)) # 2010-01-26 04:02:00
  71. >>> print(iter.get_next(datetime)) # 2010-01-30 04:02:00
  72. >>> print(iter.get_next(datetime)) # 2010-02-02 04:02:00
  73. >>>
  74. >>> iter = croniter('2 4 1 * wed', base) # 04:02 on every Wednesday OR on 1st day of month
  75. >>> print(iter.get_next(datetime)) # 2010-01-27 04:02:00
  76. >>> print(iter.get_next(datetime)) # 2010-02-01 04:02:00
  77. >>> print(iter.get_next(datetime)) # 2010-02-03 04:02:00
  78. >>>
  79. >>> iter = croniter('2 4 1 * wed', base, day_or=False) # 04:02 on every 1st day of the month if it is a Wednesday
  80. >>> print(iter.get_next(datetime)) # 2010-09-01 04:02:00
  81. >>> print(iter.get_next(datetime)) # 2010-12-01 04:02:00
  82. >>> print(iter.get_next(datetime)) # 2011-06-01 04:02:00
  83. >>>
  84. >>> iter = croniter('0 0 * * sat#1,sun#2', base) # 1st Saturday, and 2nd Sunday of the month
  85. >>> print(iter.get_next(datetime)) # 2010-02-06 00:00:00
  86. >>>
  87. >>> iter = croniter('0 0 * * 5#3,L5', base) # 3rd and last Friday of the month
  88. >>> print(iter.get_next(datetime)) # 2010-01-29 00:00:00
  89. >>> print(iter.get_next(datetime)) # 2010-02-19 00:00:00
  90. All you need to know is how to use the constructor and the ``get_next``
  91. method, the signature of these methods are listed below::
  92. >>> def __init__(self, cron_format, start_time=time.time(), day_or=True)
  93. croniter iterates along with ``cron_format`` from ``start_time``.
  94. ``cron_format`` is **min hour day month day_of_week**, you can refer to
  95. http://en.wikipedia.org/wiki/Cron for more details. The ``day_or``
  96. switch is used to control how croniter handles **day** and **day_of_week**
  97. entries. Default option is the cron behaviour, which connects those
  98. values using **OR**. If the switch is set to False, the values are connected
  99. using **AND**. This behaves like fcron and enables you to e.g. define a job that
  100. executes each 2nd Friday of a month by setting the days of month and the
  101. weekday.
  102. ::
  103. >>> def get_next(self, ret_type=float)
  104. get_next calculates the next value according to the cron expression and
  105. returns an object of type ``ret_type``. ``ret_type`` should be a ``float`` or a
  106. ``datetime`` object.
  107. Supported added for ``get_prev`` method. (>= 0.2.0)::
  108. >>> base = datetime(2010, 8, 25)
  109. >>> itr = croniter('0 0 1 * *', base)
  110. >>> print(itr.get_prev(datetime)) # 2010-08-01 00:00:00
  111. >>> print(itr.get_prev(datetime)) # 2010-07-01 00:00:00
  112. >>> print(itr.get_prev(datetime)) # 2010-06-01 00:00:00
  113. You can validate your crons using ``is_valid`` class method. (>= 0.3.18)::
  114. >>> croniter.is_valid('0 0 1 * *') # True
  115. >>> croniter.is_valid('0 wrong_value 1 * *') # False
  116. About DST
  117. =========
  118. Be sure to init your croniter instance with a TZ aware datetime for this to work!
  119. Example using pytz::
  120. >>> import pytz
  121. >>> tz = pytz.timezone("Europe/Paris")
  122. >>> local_date = tz.localize(datetime(2017, 3, 26))
  123. >>> val = croniter('0 0 * * *', local_date).get_next(datetime)
  124. Example using python_dateutil::
  125. >>> import dateutil.tz
  126. >>> tz = dateutil.tz.gettz('Asia/Tokyo')
  127. >>> local_date = datetime(2017, 3, 26, tzinfo=tz)
  128. >>> val = croniter('0 0 * * *', local_date).get_next(datetime)
  129. Example using python built in module::
  130. >>> from datetime import datetime, timezone
  131. >>> local_date = datetime(2017, 3, 26, tzinfo=timezone.utc)
  132. >>> val = croniter('0 0 * * *', local_date).get_next(datetime)
  133. About second repeats
  134. =====================
  135. Croniter is able to do second repetition crontabs form and by default seconds are the 6th field::
  136. >>> base = datetime(2012, 4, 6, 13, 26, 10)
  137. >>> itr = croniter('* * * * * 15,25', base)
  138. >>> itr.get_next(datetime) # 4/6 13:26:15
  139. >>> itr.get_next(datetime) # 4/6 13:26:25
  140. >>> itr.get_next(datetime) # 4/6 13:27:15
  141. You can also note that this expression will repeat every second from the start datetime.::
  142. >>> croniter('* * * * * *', local_date).get_next(datetime)
  143. You can also use seconds as first field::
  144. >>> itr = croniter('15,25 * * * * *', base, second_at_beginning=True)
  145. About year
  146. ===========
  147. Croniter also support year field.
  148. Year presents at the seventh field, which is after second repetition.
  149. The range of year field is from 1970 to 2099.
  150. To ignore second repetition, simply set second to ``0`` or any other const::
  151. >>> base = datetime(2012, 4, 6, 2, 6, 59)
  152. >>> itr = croniter('0 0 1 1 * 0 2020/2', base)
  153. >>> itr.get_next(datetime) # 2020 1/1 0:0:0
  154. >>> itr.get_next(datetime) # 2022 1/1 0:0:0
  155. >>> itr.get_next(datetime) # 2024 1/1 0:0:0
  156. Support for start_time shifts
  157. ==============================
  158. See https://github.com/kiorky/croniter/pull/76,
  159. You can set start_time=, then expand_from_start_time=True for your generations to be computed from start_time instead of calendar days::
  160. >>> from pprint import pprint
  161. >>> iter = croniter('0 0 */7 * *', start_time=datetime(2024, 7, 11), expand_from_start_time=True);pprint([iter.get_next(datetime) for a in range(10)])
  162. [datetime.datetime(2024, 7, 18, 0, 0),
  163. datetime.datetime(2024, 7, 25, 0, 0),
  164. datetime.datetime(2024, 8, 4, 0, 0),
  165. datetime.datetime(2024, 8, 11, 0, 0),
  166. datetime.datetime(2024, 8, 18, 0, 0),
  167. datetime.datetime(2024, 8, 25, 0, 0),
  168. datetime.datetime(2024, 9, 4, 0, 0),
  169. datetime.datetime(2024, 9, 11, 0, 0),
  170. datetime.datetime(2024, 9, 18, 0, 0),
  171. datetime.datetime(2024, 9, 25, 0, 0)]
  172. >>> # INSTEAD OF THE DEFAULT BEHAVIOR:
  173. >>> iter = croniter('0 0 */7 * *', start_time=datetime(2024, 7, 11), expand_from_start_time=False);pprint([iter.get_next(datetime) for a in range(10)])
  174. [datetime.datetime(2024, 7, 15, 0, 0),
  175. datetime.datetime(2024, 7, 22, 0, 0),
  176. datetime.datetime(2024, 7, 29, 0, 0),
  177. datetime.datetime(2024, 8, 1, 0, 0),
  178. datetime.datetime(2024, 8, 8, 0, 0),
  179. datetime.datetime(2024, 8, 15, 0, 0),
  180. datetime.datetime(2024, 8, 22, 0, 0),
  181. datetime.datetime(2024, 8, 29, 0, 0),
  182. datetime.datetime(2024, 9, 1, 0, 0),
  183. datetime.datetime(2024, 9, 8, 0, 0)]
  184. Testing if a date matches a crontab
  185. ===================================
  186. Test for a match with (>=0.3.32)::
  187. >>> croniter.match("0 0 * * *", datetime(2019, 1, 14, 0, 0, 0, 0))
  188. True
  189. >>> croniter.match("0 0 * * *", datetime(2019, 1, 14, 0, 2, 0, 0))
  190. False
  191. >>>
  192. >>> croniter.match("2 4 1 * wed", datetime(2019, 1, 1, 4, 2, 0, 0)) # 04:02 on every Wednesday OR on 1st day of month
  193. True
  194. >>> croniter.match("2 4 1 * wed", datetime(2019, 1, 1, 4, 2, 0, 0), day_or=False) # 04:02 on every 1st day of the month if it is a Wednesday
  195. False
  196. Testing if a crontab matches in datetime range
  197. ==============================================
  198. Test for a match_range with (>=2.0.3)::
  199. >>> croniter.match_range("0 0 * * *", datetime(2019, 1, 13, 0, 59, 0, 0), datetime(2019, 1, 14, 0, 1, 0, 0))
  200. True
  201. >>> croniter.match_range("0 0 * * *", datetime(2019, 1, 13, 0, 1, 0, 0), datetime(2019, 1, 13, 0, 59, 0, 0))
  202. False
  203. >>> croniter.match_range("2 4 1 * wed", datetime(2019, 1, 1, 3, 2, 0, 0), datetime(2019, 1, 1, 5, 1, 0, 0))
  204. # 04:02 on every Wednesday OR on 1st day of month
  205. True
  206. >>> croniter.match_range("2 4 1 * wed", datetime(2019, 1, 1, 3, 2, 0, 0), datetime(2019, 1, 1, 5, 2, 0, 0), day_or=False)
  207. # 04:02 on every 1st day of the month if it is a Wednesday
  208. False
  209. Gaps between date matches
  210. =========================
  211. For performance reasons, croniter limits the amount of CPU cycles spent attempting to find the next match.
  212. Starting in v0.3.35, this behavior is configurable via the ``max_years_between_matches`` parameter, and the default window has been increased from 1 year to 50 years.
  213. The defaults should be fine for many use cases.
  214. Applications that evaluate multiple cron expressions or handle cron expressions from untrusted sources or end-users should use this parameter.
  215. Iterating over sparse cron expressions can result in increased CPU consumption or a raised ``CroniterBadDateError`` exception which indicates that croniter has given up attempting to find the next (or previous) match.
  216. Explicitly specifying ``max_years_between_matches`` provides a way to limit CPU utilization and simplifies the iterable interface by eliminating the need for ``CroniterBadDateError``.
  217. The difference in the iterable interface is based on the reasoning that whenever ``max_years_between_matches`` is explicitly agreed upon, there is no need for croniter to signal that it has given up; simply stopping the iteration is preferable.
  218. This example matches 4 AM Friday, January 1st.
  219. Since January 1st isn't often a Friday, there may be a few years between each occurrence.
  220. Setting the limit to 15 years ensures all matches::
  221. >>> it = croniter("0 4 1 1 fri", datetime(2000,1,1), day_or=False, max_years_between_matches=15).all_next(datetime)
  222. >>> for i in range(5):
  223. ... print(next(it))
  224. ...
  225. 2010-01-01 04:00:00
  226. 2016-01-01 04:00:00
  227. 2021-01-01 04:00:00
  228. 2027-01-01 04:00:00
  229. 2038-01-01 04:00:00
  230. However, when only concerned with dates within the next 5 years, simply set ``max_years_between_matches=5`` in the above example.
  231. This will result in no matches found, but no additional cycles will be wasted on unwanted matches far in the future.
  232. Iterating over a range using cron
  233. =================================
  234. Find matches within a range using the ``croniter_range()`` function. This is much like the builtin ``range(start,stop,step)`` function, but for dates. The `step` argument is a cron expression.
  235. Added in (>=0.3.34)
  236. List the first Saturday of every month in 2019::
  237. >>> from croniter import croniter_range
  238. >>> for dt in croniter_range(datetime(2019, 1, 1), datetime(2019, 12, 31), "0 0 * * sat#1"):
  239. >>> print(dt)
  240. Hashed expressions
  241. ==================
  242. croniter supports Jenkins-style hashed expressions, using the "H" definition keyword and the required hash_id keyword argument.
  243. Hashed expressions remain consistent, given the same hash_id, but different hash_ids will evaluate completely different to each other.
  244. This allows, for example, for an even distribution of differently-named jobs without needing to manually spread them out.
  245. >>> itr = croniter("H H * * *", hash_id="hello")
  246. >>> itr.get_next(datetime)
  247. datetime.datetime(2021, 4, 10, 11, 10)
  248. >>> itr.get_next(datetime)
  249. datetime.datetime(2021, 4, 11, 11, 10)
  250. >>> itr = croniter("H H * * *", hash_id="hello")
  251. >>> itr.get_next(datetime)
  252. datetime.datetime(2021, 4, 10, 11, 10)
  253. >>> itr = croniter("H H * * *", hash_id="bonjour")
  254. >>> itr.get_next(datetime)
  255. datetime.datetime(2021, 4, 10, 20, 52)
  256. Random expressions
  257. ==================
  258. Random "R" definition keywords are supported, and remain consistent only within their croniter() instance.
  259. >>> itr = croniter("R R * * *")
  260. >>> itr.get_next(datetime)
  261. datetime.datetime(2021, 4, 10, 22, 56)
  262. >>> itr.get_next(datetime)
  263. datetime.datetime(2021, 4, 11, 22, 56)
  264. >>> itr = croniter("R R * * *")
  265. >>> itr.get_next(datetime)
  266. datetime.datetime(2021, 4, 11, 4, 19)
  267. Note about Ranges
  268. =================
  269. Note that as a deviation from cron standard, croniter is somehow laxist with ranges and will allow ranges of ``Jan-Dec``, & ``Sun-Sat`` in reverse way and interpret them as following examples:
  270. - ``Apr-Jan``: from April to january
  271. - ``Sat-Sun``: Saturday, Sunday
  272. - ``Wed-Sun``: Wednesday to Saturday, Sunday
  273. Please note that if a /step is given, it will be respected.
  274. Note about Sunday
  275. =================
  276. Note that as a deviation from cron standard, croniter like numerous cron implementations supports ``SUNDAY`` to be expressed as ``DAY7``, allowing such expressions:
  277. - ``0 0 * * 7``
  278. - ``0 0 * * 6-7``
  279. - ``0 0 * * 6,7``
  280. Keyword expressions
  281. ===================
  282. Vixie cron-style "@" keyword expressions are supported.
  283. What they evaluate to depends on whether you supply hash_id: no hash_id corresponds to Vixie cron definitions (exact times, minute resolution), while with hash_id corresponds to Jenkins definitions (hashed within the period, second resolution).
  284. ============ ============ ================
  285. Keyword No hash_id With hash_id
  286. ============ ============ ================
  287. @midnight 0 0 * * * H H(0-2) * * * H
  288. @hourly 0 * * * * H * * * * H
  289. @daily 0 0 * * * H H * * * H
  290. @weekly 0 0 * * 0 H H * * H H
  291. @monthly 0 0 1 * * H H H * * H
  292. @yearly 0 0 1 1 * H H H H * H
  293. @annually 0 0 1 1 * H H H H * H
  294. ============ ============ ================
  295. Upgrading
  296. ==========
  297. To 2.0.0
  298. ---------
  299. - Install or upgrade pytz by using version specified requirements/base.txt if you have it installed `<=2021.1`.
  300. Develop this package
  301. ====================
  302. ::
  303. git clone https://github.com/kiorky/croniter.git
  304. cd croniter
  305. virtualenv --no-site-packages venv3
  306. venv3/bin/pip install --upgrade -r requirements/test.txt -r requirements/lint.txt -r requirements/format.txt -r requirements/tox.txt
  307. venv3/bin/black src/
  308. venv3/bin/isort src/
  309. venv3/bin/tox --current-env -e fmt,lint,test
  310. Testing under py2
  311. ==================
  312. Install prerequisisites ::
  313. # install py 2 with eg: apt install python2.7
  314. mkdir venv2 && curl -sSL "https://github.com/pypa/get-virtualenv/blob/20.27.0/public/2.7/virtualenv.pyz?raw=true" > venv2/venv && python2 venv2/venv venv2
  315. venv2/bin/python2 -m pip install -r ./requirements/test.txt
  316. Run tests::
  317. ./venv2/bin/pytest src
  318. Make a new release
  319. ====================
  320. We use zest.fullreleaser, a great release infrastructure.
  321. Do and follow these instructions
  322. ::
  323. venv3/bin/pip install --upgrade -r requirements/release.txt
  324. ./release.sh
  325. Contributors
  326. ===============
  327. Thanks to all who have contributed to this project!
  328. If you have contributed and your name is not listed below please let us know.
  329. - Aarni Koskela (akx)
  330. - chris-baynes
  331. - djmitche
  332. - evanpurkhiser
  333. - GreatCombinator
  334. - Hinnack
  335. - ipartola
  336. - jlsandell
  337. - kiorky
  338. - lowell80 (Kintyre)
  339. - mag009
  340. - mrmachine
  341. - Ryan Finnie (rfinnie)
  342. - salitaba
  343. - scop
  344. - shazow
  345. - yuzawa-san
  346. - zed2015
  347. Changelog
  348. ==============
  349. 6.0.0 (2024-12-17)
  350. ------------------
  351. - Announce for now that croniter dev is ended (CRA).
  352. - Rework timestamp_to_datetime to use whatever timezone [kiorky]
  353. - Make datetime_to_timestamp & timestamp_to_datetime public [kiorky]
  354. - Fix EPOCH calculation in case of non UTC & 32 bits based systems [kiorky]
  355. - Apply isort formatter [kiorky]
  356. - Reintegrate test_speed [kiorky]
  357. - Apply black formatter [evanpurkhiser, kiorky]
  358. - Code quality changes [evanpurkhiser, kiorky]
  359. - Remove unused _get_caller_globals_and_locals [evanpurkhiser]
  360. - Remove single-use bad_length [evanpurkhiser]
  361. - Remove unused `days` in `proc_month` [evanpurkhiser]
  362. - Use `field_index` over `i` for readability [evanpurkhiser]
  363. - Always use `"""` for docstrings [evanpurkhiser]
  364. - Make helper instance methods that do not use self static [evanpurkhiser]
  365. - Remove unusd call to sys.exc_info [evanpurkhiser]
  366. - Remove unused `ALPHAS` [evanpurkhiser]
  367. - Improve `croniter.expand` documentation [evanpurkhiser]
  368. 5.0.1 (2024-10-29)
  369. ------------------
  370. - Community wanted: Reintroduce 7 as DayOfWeek in deviation from standard cron (#90). [kiorky]
  371. 4.0.0 (2024-10-28)
  372. ------------------
  373. - Remove DayOfWeek alias 7 to DayOfWeek 0 to stick to standard cron (#90). [kiorky]
  374. - Fix DOW ranges calculations when lastday is a Sunday. [kiorky]
  375. 3.0.4 (2024-10-25)
  376. ------------------
  377. - Fix overflow on 32bits systems (#87) [kiorky]
  378. - Fix python2 testing (related to #93) [kiorky]
  379. - Modernize packaging. Special thanks to Aarni Koskela (akx) for all the inputs. [kiorky, akx]
  380. 3.0.3 (2024-07-26)
  381. ------------------
  382. - fix lint [kiorky]
  383. 3.0.2 (2024-07-26)
  384. ------------------
  385. - Fix start_time not respected in get_next/get_prev/all_next/all_prev (#86) [hesstobi, kiorky]
  386. 3.0.1 (2024-07-25)
  387. ------------------
  388. - Add an `update_current` argument to get_next/get_prev/all_next/all_prev to facilitate writing of some downstream code, see #83. [kiorky]
  389. 3.0.0 (2024-07-23)
  390. ------------------
  391. - Support for year field [zhouyizhen, kiorky]
  392. - Better support for 6 fields (second), and 7 fields crons [zhouyizhen, kiorky]
  393. - Better fix hashed expressions omitting some entries (#82, #42, #30) fix is retained over #42 initial fix [zhouyizhen, kiorky]
  394. - Ensure match return false when not time available (#81) [zhouyizhen, kiorky]
  395. 2.0.7 (2024-07-16)
  396. ------------------
  397. - fix doc
  398. 2.0.6 (2024-07-16)
  399. ------------------
  400. - Implement second_at_beginning [zhouyizhen, kiorky]
  401. - Support question mark as wildcard [zhouyizhen, kiorky]
  402. - Support to start a cron from a reference start time [mghextreme, kiorky]
  403. 2.0.5 (2024-04-20)
  404. ------------------
  405. - No changes, fix lint [kiorky]
  406. 2.0.4 (2024-04-20)
  407. ------------------
  408. - Support hashid strings in is_valid [george-kuanli-peng, kiorky]
  409. - Avoid over-optimization in crontab expansions [Cherie0125, liqirui <liqirui@baidu.com>, kiorky]
  410. 2.0.3 (2024-03-19)
  411. ------------------
  412. - Add match_range function [salitaba]
  413. 2.0.2 (2024-02-29)
  414. ------------------
  415. - fix leap year (29 days in February) [zed2015]
  416. 2.0.1 (2023-10-11)
  417. ------------------
  418. - Fix release issue [kiorky]
  419. 2.0.0 (2023-10-10)
  420. ------------------
  421. - Add Python 3.12 support [rafsaf]
  422. - Make major release instructions [kiorky]
  423. 1.4.1 (2023-06-15)
  424. ------------------
  425. - Make a retrocompatible version of 1.4.0 change about supporting VIXIECRON bug. (fix #47)
  426. [kiorky]
  427. 1.4.0 (2023-06-15)
  428. ------------------
  429. - Added "implement_cron_bug" flag to make the cron parser compatible with a bug in Vixie/ISC Cron
  430. [kiorky, David White <dwhite2@cisco.com>]
  431. *WARNING*: EXPAND METHOD CHANGES RETURN VALUE
  432. 1.3.15 (2023-05-25)
  433. -------------------
  434. - Fix hashed expressions omitting some entries
  435. [@waltervos/Walter Vos <walter.vos@ns.nl>]
  436. - Enhance .match() precision for 6 position expressions
  437. [@szpol/szymon <szymon.polinkiewicz@gmail.com>]
  438. 1.3.14 (2023-04-12)
  439. -------------------
  440. - Lint
  441. 1.3.13 (2023-04-12)
  442. -------------------
  443. - Add check for range begin/end
  444. 1.3.12 (2023-04-12)
  445. -------------------
  446. - restore py2 compat
  447. 1.3.11 (2023-04-12)
  448. -------------------
  449. - Do not expose `i` into global namespace
  450. 1.3.10 (2023-04-07)
  451. -------------------
  452. - Fix DOW hash parsing [kiorky]
  453. - better error handling on py3 [kiorky]
  454. 1.3.8 (2022-11-22)
  455. ------------------
  456. - Add Python 3.11 support and move docs files to main folder [rafsaf]
  457. 1.3.7 (2022-09-06)
  458. ------------------
  459. - fix tests
  460. - Fix croniter_range infinite loop [Shachar Snapiri <ssnapiri@paloaltonetworks.com>]
  461. 1.3.5 (2022-05-14)
  462. ------------------
  463. - Add Python 3.10 support [eelkevdbos]
  464. 1.3.4 (2022-02-18)
  465. ------------------
  466. - Really fix compat for tests under py27
  467. [kiorky]
  468. 1.3.3 (2022-02-18)
  469. ------------------
  470. - Fix compat for tests under py27
  471. [kiorky]
  472. 1.3.2 (2022-02-18)
  473. ------------------
  474. - Fix #12: regressions with set_current
  475. [kiorky, agateblue]
  476. 1.3.1 (2022-02-15)
  477. ------------------
  478. - Restore compat with python2
  479. [kiorky]
  480. 1.3.0 (2022-02-15)
  481. ------------------
  482. - Add a way to make next() easier to use. This fixes #11
  483. [kiorky]
  484. 1.2.0 (2022-01-14)
  485. ------------------
  486. - 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. See https://github.com/kiorky/croniter/issues/6
  487. [kiorky]
  488. 1.1.0 (2021-12-03)
  489. ------------------
  490. - 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. See https://github.com/kiorky/croniter/issues/6
  491. [kiorky]
  492. 1.0.15 (2021-06-25)
  493. -------------------
  494. - restore py2 [kiorky]
  495. 1.0.14 (2021-06-25)
  496. -------------------
  497. - better type checks [kiorky]
  498. 1.0.13 (2021-05-06)
  499. -------------------
  500. - Fix ZeroDivisionError with ``* * R/0 * *``
  501. [cuu508]
  502. 1.0.12 (2021-04-13)
  503. -------------------
  504. - Add support for hashed/random/keyword expressions
  505. Ryan Finnie (rfinnie)
  506. - Review support support for hashed/random/keyword expression and add expanders reactor
  507. [ kiorky ]
  508. 1.0.11 (2021-04-07)
  509. -------------------
  510. - fix bug: bad case:``0 6 30 3 *``
  511. [zed2015(zhangchi)]
  512. - Add support for ``L`` in the day_of_week component. This enable expressions like ``* * * * L4``, which means last Thursday of the month. This resolves #159.
  513. [Kintyre]
  514. - Create ``CroniterUnsupportedSyntaxError`` exception for situations where CRON syntax may be valid but some combinations of features is not supported.
  515. Currently, this is used when the ``day_of_week`` component has a combination of literal values and nth/last syntax at the same time.
  516. For example, ``0 0 * * 1,L6`` or ``0 0 * * 15,sat#1`` will both raise this exception because of mixing literal days of the week with nth-weekday or last-weekday syntax.
  517. This *may* impact existing cron expressions in prior releases, because ``0 0 * * 15,sat#1`` was previously allowed but incorrectly handled.
  518. [Kintyre]
  519. - Update ``croniter_range()`` to allow an alternate ``croniter`` class to be used. Helpful when using a custom class derived from croniter.
  520. [Kintyre]
  521. 1.0.10 (2021-03-25)
  522. -------------------
  523. - Remove external library ``natsort``.
  524. Sorting of cron expression components now handled with ``sorted()`` with a custom ``key`` function.
  525. [Kintyre]
  526. 1.0.9 (2021-03-23)
  527. ------------------
  528. - Remove futures dependency
  529. [kiorky]
  530. 1.0.8 (2021-03-06)
  531. ------------------
  532. - Update `_expand` to lowercase each component of the expression.
  533. This is in relation to #157. With this change, croniter accepts and correctly handles `* * 10-L * *`.
  534. [cuu508]
  535. 1.0.7 (2021-03-02)
  536. ------------------
  537. - Fix _expand to reject int literals with underscores
  538. [cuu508]
  539. - Remove a debug statement to make flake8 happy
  540. [cuu508]
  541. 1.0.6 (2021-02-01)
  542. ------------------
  543. - Fix combination of star and invalid expression bugs
  544. [kiorky]
  545. 1.0.5 (2021-01-29)
  546. ------------------
  547. - Security fix: fix overflow when using cron ranges
  548. [kiorky]
  549. 1.0.4 (2021-01-29)
  550. ------------------
  551. - Spelling fix release
  552. 1.0.3 (2021-01-29)
  553. ------------------
  554. - Fix #155: raise CroniterBadCronError when error syntax
  555. [kiorky]
  556. 1.0.2 (2021-01-19)
  557. ------------------
  558. - Fix match when datetime has microseconds
  559. [kiorky]
  560. 1.0.1 (2021-01-06)
  561. ------------------
  562. - no changes, just to make sense with new semver2 (making croniter on a stable state)
  563. [kiorky]
  564. 0.3.37 (2020-12-31)
  565. -------------------
  566. - Added Python 3.8 and 3.9 support
  567. [eumiro]
  568. 0.3.36 (2020-11-02)
  569. -------------------
  570. - Updated docs section regarding ``max_years_between_matches`` to be more shorter and hopefully more relevant.
  571. [Kintyre]
  572. - Don't install tests
  573. [scop]
  574. 0.3.35 (2020-10-11)
  575. -------------------
  576. - Handle L in ranges. This fixes #142.
  577. [kiorky]
  578. - Add a new initialization parameter ``max_years_between_matches`` to 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.
  579. [Kintyre]
  580. - The ``croniter_range()`` function was updated to automatically determines the appropriate ``max_years_between_matches`` value, this preventing handling of the ``CroniterBadDateError`` exception.
  581. [Kintyre]
  582. - Updated exception handling classes: ``CroniterBadDateError`` now only
  583. applies during date finding operations (next/prev), and all parsing errors can now be caught using ``CroniterBadCronError``. The ``CroniterNotAlphaError`` exception is now a subclass of ``CroniterBadCronError``. A brief description of each exception class was added as an inline docstring.
  584. [Kintyre]
  585. - Updated iterable interfaces to replace the ``CroniterBadDateError`` with ``StopIteration`` if (and only if) the ``max_years_between_matches`` argument 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.
  586. [Kintyre]
  587. - Minor docs update
  588. [Kintyre]
  589. 0.3.34 (2020-06-19)
  590. -------------------
  591. - Feat ``croniter_range(start, stop, cron)``
  592. [Kintyre]
  593. - Optimization for poorly written cron expression
  594. [Kintyre]
  595. 0.3.33 (2020-06-15)
  596. -------------------
  597. - Make dateutil tz support more official
  598. [Kintyre]
  599. - Feat/support for day or
  600. [田口信元]
  601. 0.3.32 (2020-05-27)
  602. -------------------
  603. - document seconds repeats, fixes #122
  604. [kiorky]
  605. - Implement match method, fixes #54
  606. [kiorky]
  607. - Adding tests for #127 (test more DSTs and croniter behavior around)
  608. [kiorky]
  609. - Changed lag_hours comparison to absolute to manage dst boundary when getting previous
  610. [Sokkka]
  611. 0.3.31 (2020-01-02)
  612. -------------------
  613. - Fix get_next() when start_time less then 1s before next instant
  614. [AlexHill]
  615. 0.3.30 (2019-04-20)
  616. -------------------
  617. - credits
  618. 0.3.29 (2019-03-26)
  619. -------------------
  620. - credits
  621. - history stripping (security)
  622. - Handle -Sun notation, This fixes `#119 <https://github.com/taichino/croniter/issues/119>`_.
  623. [kiorky]
  624. - Handle invalid ranges correctly, This fixes `#114 <https://github.com/taichino/croniter/issues/114>`_.
  625. [kiorky]
  626. 0.3.25 (2018-08-07)
  627. -------------------
  628. - Pypi hygiene
  629. [hugovk]
  630. 0.3.24 (2018-06-20)
  631. -------------------
  632. - fix `#107 <https://github.com/taichino/croniter/issues/107>`_: microsecond threshold
  633. [kiorky]
  634. 0.3.23 (2018-05-23)
  635. -------------------
  636. - fix ``get_next`` while preserving the fix of ``get_prev`` in 7661c2aaa
  637. [Avikam Agur <avikam@pagaya-inv.com>]
  638. 0.3.22 (2018-05-16)
  639. -------------------
  640. - Don't count previous minute if now is dynamic
  641. If the code is triggered from 5-asterisk based cron
  642. ``get_prev`` based on ``datetime.now()`` is expected to return
  643. current cron iteration and not previous execution.
  644. [Igor Khrol <igor.khrol@toptal.com>]
  645. 0.3.20 (2017-11-06)
  646. -------------------
  647. - More DST fixes
  648. [Kevin Rose <kbrose@github>]
  649. 0.3.19 (2017-08-31)
  650. -------------------
  651. - fix #87: backward dst changes
  652. [kiorky]
  653. 0.3.18 (2017-08-31)
  654. -------------------
  655. - Add is valid method, refactor errors
  656. [otherpirate, Mauro Murari <mauro_murari@hotmail.com>]
  657. 0.3.17 (2017-05-22)
  658. -------------------
  659. - DOW occurrence sharp style support.
  660. [kiorky, Kengo Seki <sekikn@apache.org>]
  661. 0.3.16 (2017-03-15)
  662. -------------------
  663. - Better test suite [mrcrilly@github]
  664. - DST support [kiorky]
  665. 0.3.15 (2017-02-16)
  666. -------------------
  667. - fix bug around multiple conditions and range_val in
  668. _get_prev_nearest_diff.
  669. [abeja-yuki@github]
  670. 0.3.14 (2017-01-25)
  671. -------------------
  672. - issue #69: added day_or option to change behavior when day-of-month and
  673. day-of-week is given
  674. [Andreas Vogl <a.vogl@hackner-security.com>]
  675. 0.3.13 (2016-11-01)
  676. -------------------
  677. - `Real fix for #34 <https://github.com/taichino/croniter/pull/73>`_
  678. [kiorky@github]
  679. - `Modernize test infra <https://github.com/taichino/croniter/pull/72>`_
  680. [kiorky@github]
  681. - `Release as a universal wheel <https://github.com/kiorky/croniter/pull/16>`_
  682. [adamchainz@github]
  683. - `Raise ValueError on negative numbers <https://github.com/taichino/croniter/pull/63>`_
  684. [josegonzalez@github]
  685. - `Compare types using "issubclass" instead of exact match <https://github.com/taichino/croniter/pull/70>`_
  686. [darkk@github]
  687. - `Implement step cron with a variable base <https://github.com/taichino/croniter/pull/60>`_
  688. [josegonzalez@github]
  689. 0.3.12 (2016-03-10)
  690. -------------------
  691. - support setting ret_type in __init__ [Brent Tubbs <brent.tubbs@gmail.com>]
  692. 0.3.11 (2016-01-13)
  693. -------------------
  694. - Bug fix: The get_prev API crashed when last day of month token was used. Some
  695. essential logic was missing.
  696. [Iddo Aviram <iddo.aviram@similarweb.com>]
  697. 0.3.10 (2015-11-29)
  698. -------------------
  699. - The functionality of 'l' as day of month was broken, since the month variable
  700. was not properly updated
  701. [Iddo Aviram <iddo.aviram@similarweb.com>]
  702. 0.3.9 (2015-11-19)
  703. ------------------
  704. - Don't use datetime functions python 2.6 doesn't support
  705. [petervtzand]
  706. 0.3.8 (2015-06-23)
  707. ------------------
  708. - Truncate microseconds by setting to 0
  709. [Corey Wright]
  710. 0.3.7 (2015-06-01)
  711. ------------------
  712. - converting sun in range sun-thu transforms to int 0 which is
  713. recognized as empty string; the solution was to convert sun to string "0"
  714. 0.3.6 (2015-05-29)
  715. ------------------
  716. - Fix default behavior when no start_time given
  717. Default value for ``start_time`` parameter is calculated at module init time rather than call time.
  718. - Fix timezone support and stop depending on the system time zone
  719. 0.3.5 (2014-08-01)
  720. ------------------
  721. - support for 'l' (last day of month)
  722. 0.3.4 (2014-01-30)
  723. ------------------
  724. - Python 3 compat
  725. - QA Release
  726. 0.3.3 (2012-09-29)
  727. ------------------
  728. - proper packaging