0
# Core Iteration
1
2
The main croniter class provides datetime iteration capabilities based on cron expressions. It supports both forward and backward iteration, timezone handling, various cron formats (5, 6, and 7 fields), and advanced features like hashed and random expressions.
3
4
## Capabilities
5
6
### Croniter Class
7
8
The core class that parses cron expressions and provides iteration functionality.
9
10
```python { .api }
11
class croniter:
12
def __init__(
13
self,
14
expr_format: str,
15
start_time=None,
16
ret_type=float,
17
day_or=True,
18
max_years_between_matches=None,
19
is_prev=False,
20
hash_id=None,
21
implement_cron_bug=False,
22
second_at_beginning=None,
23
expand_from_start_time=False,
24
):
25
"""
26
Initialize croniter instance.
27
28
Parameters:
29
- expr_format: Cron expression string (e.g., '0 0 * * *', '*/5 * * * *')
30
- start_time: Starting datetime (datetime object, timestamp, or None for current time)
31
- ret_type: Return type for get_next/get_prev (float for timestamp, datetime for datetime object)
32
- day_or: How to handle day and day_of_week fields (True=OR logic, False=AND logic)
33
- max_years_between_matches: Limit CPU cycles for sparse expressions (default 50)
34
- is_prev: Whether iteration goes backward (default False)
35
- hash_id: Hash ID for Jenkins-style hashed expressions (bytes or str)
36
- implement_cron_bug: Enable bug compatibility mode (default False)
37
- second_at_beginning: Put seconds field at beginning instead of end
38
- expand_from_start_time: Calculate intervals from start_time instead of calendar
39
"""
40
```
41
42
### Forward Iteration
43
44
Get next matching datetime values.
45
46
```python { .api }
47
def get_next(self, ret_type=None, start_time=None, update_current=True):
48
"""
49
Get the next datetime matching the cron expression.
50
51
Parameters:
52
- ret_type: Override return type (float, datetime, or None for instance default)
53
- start_time: Override start time for this calculation
54
- update_current: Whether to update internal current time (default True)
55
56
Returns:
57
Next matching datetime as specified ret_type
58
"""
59
60
def all_next(self, ret_type=None, start_time=None, update_current=None):
61
"""
62
Generator yielding consecutive next matching datetimes.
63
64
Parameters:
65
- ret_type: Return type for each yielded value
66
- start_time: Override start time
67
- update_current: Whether to update current time for each iteration
68
69
Yields:
70
Consecutive next matching datetimes
71
"""
72
```
73
74
### Backward Iteration
75
76
Get previous matching datetime values.
77
78
```python { .api }
79
def get_prev(self, ret_type=None, start_time=None, update_current=True):
80
"""
81
Get the previous datetime matching the cron expression.
82
83
Parameters:
84
- ret_type: Override return type (float, datetime, or None for instance default)
85
- start_time: Override start time for this calculation
86
- update_current: Whether to update internal current time (default True)
87
88
Returns:
89
Previous matching datetime as specified ret_type
90
"""
91
92
def all_prev(self, ret_type=None, start_time=None, update_current=None):
93
"""
94
Generator yielding consecutive previous matching datetimes.
95
96
Parameters:
97
- ret_type: Return type for each yielded value
98
- start_time: Override start time
99
- update_current: Whether to update current time for each iteration
100
101
Yields:
102
Consecutive previous matching datetimes
103
"""
104
```
105
106
### State Management
107
108
Manage the current datetime state of the iterator.
109
110
```python { .api }
111
def get_current(self, ret_type=None):
112
"""
113
Get the current datetime without advancing iteration.
114
115
Parameters:
116
- ret_type: Return type (float, datetime, or None for instance default)
117
118
Returns:
119
Current datetime as specified ret_type
120
"""
121
122
def set_current(self, start_time, force=True):
123
"""
124
Set the current datetime for iteration.
125
126
Parameters:
127
- start_time: New current time (datetime object or timestamp)
128
- force: Whether to force update even if current time is already set
129
130
Returns:
131
Updated current timestamp
132
"""
133
```
134
135
### Iterator Protocol
136
137
Croniter implements Python's iterator protocol for easy iteration.
138
139
```python { .api }
140
def __iter__(self):
141
"""Return self as iterator"""
142
143
def __next__(self):
144
"""Get next value (forward or backward based on is_prev flag)"""
145
146
def iter(self, *args, **kwargs):
147
"""Return appropriate iterator (all_next or all_prev based on is_prev flag)"""
148
```
149
150
### Utility Methods
151
152
Static methods for datetime conversion and calculation.
153
154
```python { .api }
155
@staticmethod
156
def datetime_to_timestamp(d):
157
"""
158
Convert datetime object to UNIX timestamp.
159
160
Parameters:
161
- d: datetime object
162
163
Returns:
164
UNIX timestamp as float
165
"""
166
167
@staticmethod
168
def timedelta_to_seconds(td):
169
"""
170
Convert timedelta object to seconds.
171
172
Parameters:
173
- td: timedelta object
174
175
Returns:
176
Total seconds as float
177
"""
178
179
def timestamp_to_datetime(self, timestamp, tzinfo=MARKER):
180
"""
181
Convert UNIX timestamp to datetime object.
182
183
Parameters:
184
- timestamp: UNIX timestamp
185
- tzinfo: Timezone info (uses MARKER sentinel by default, falls back to instance timezone)
186
187
Returns:
188
datetime object with proper timezone
189
"""
190
```
191
192
### Expression Expansion
193
194
Class method for expanding and normalizing cron expressions.
195
196
```python { .api }
197
@classmethod
198
def expand(
199
cls,
200
expr_format,
201
hash_id=None,
202
second_at_beginning=False,
203
from_timestamp=None,
204
):
205
"""
206
Expand cron expression into normalized form with field-by-field breakdown.
207
208
Parameters:
209
- expr_format: Cron expression string to expand
210
- hash_id: Hash ID for hashed expressions (Jenkins-style "H")
211
- second_at_beginning: Put seconds field at beginning instead of end
212
- from_timestamp: Reference timestamp for expansion calculations
213
214
Returns:
215
tuple: (expanded_expression_list, field_count)
216
217
The expanded expression is a list where each element corresponds to
218
a cron field with all possible values explicitly listed.
219
"""
220
```
221
222
### Static Utility Methods
223
224
Additional static methods for datetime calculations and validation.
225
226
```python { .api }
227
@staticmethod
228
def is_leap(year):
229
"""
230
Check if a year is a leap year.
231
232
Parameters:
233
- year: Year to check (int)
234
235
Returns:
236
bool: True if leap year, False otherwise
237
"""
238
239
@classmethod
240
def value_alias(cls, val, field_index, len_expressions=UNIX_CRON_LEN):
241
"""
242
Convert field value aliases to numeric values.
243
244
Parameters:
245
- val: Value to convert (may be numeric or text alias like 'jan', 'mon')
246
- field_index: Which cron field this value belongs to
247
- len_expressions: Length of cron expression (5, 6, or 7 fields)
248
249
Returns:
250
Converted numeric value
251
"""
252
```
253
254
## Usage Examples
255
256
### Basic Forward Iteration
257
258
```python
259
from croniter import croniter
260
from datetime import datetime
261
262
# Every 15 minutes
263
base = datetime(2010, 1, 25, 4, 46)
264
iter = croniter('*/15 * * * *', base)
265
266
for i in range(5):
267
print(iter.get_next(datetime))
268
# 2010-01-25 05:00:00
269
# 2010-01-25 05:15:00
270
# 2010-01-25 05:30:00
271
# 2010-01-25 05:45:00
272
# 2010-01-25 06:00:00
273
```
274
275
### Backward Iteration
276
277
```python
278
# Get previous matches
279
base = datetime(2010, 8, 25)
280
iter = croniter('0 0 1 * *', base) # First day of each month
281
282
print(iter.get_prev(datetime)) # 2010-08-01 00:00:00
283
print(iter.get_prev(datetime)) # 2010-07-01 00:00:00
284
print(iter.get_prev(datetime)) # 2010-06-01 00:00:00
285
```
286
287
### Generator Usage
288
289
```python
290
# Using generators for continuous iteration
291
iter = croniter('0 */6 * * *', datetime(2010, 1, 1)) # Every 6 hours
292
293
# Get first 10 matches
294
matches = [next(iter.all_next(datetime)) for _ in range(10)]
295
296
# Or use as iterator directly
297
for i, dt in enumerate(iter):
298
if i >= 10:
299
break
300
print(dt)
301
```
302
303
### Timezone Handling
304
305
```python
306
import pytz
307
from datetime import datetime
308
309
# Use timezone-aware datetime
310
tz = pytz.timezone("Europe/Paris")
311
local_date = tz.localize(datetime(2017, 3, 26))
312
iter = croniter('0 0 * * *', local_date)
313
314
next_match = iter.get_next(datetime)
315
print(next_match) # Properly handles DST transitions
316
```
317
318
### Day/Dayofweek Logic
319
320
```python
321
# OR logic (default): run on 1st day of month OR on Wednesdays
322
iter = croniter('2 4 1 * wed', base, day_or=True)
323
324
# AND logic: run on 1st day of month IF it's a Wednesday
325
iter = croniter('2 4 1 * wed', base, day_or=False)
326
```
327
328
### Performance Tuning
329
330
```python
331
# Limit search window for sparse expressions
332
iter = croniter(
333
"0 4 1 1 fri", # 4 AM on January 1st if it's Friday (very sparse)
334
datetime(2000, 1, 1),
335
day_or=False,
336
max_years_between_matches=15 # Limit to 15 years
337
)
338
339
# Use all_next() - won't raise CroniterBadDateError when limit exceeded
340
for match in iter.all_next(datetime):
341
print(match)
342
```
343
344
### Expression Expansion Usage
345
346
```python
347
from croniter import croniter
348
349
# Expand a basic cron expression
350
expanded, field_count = croniter.expand('*/5 0-12 * * mon-fri')
351
print(f"Fields: {field_count}")
352
print(f"Expanded: {expanded}")
353
354
# Expand with hashed expressions
355
expanded, _ = croniter.expand('H H * * *', hash_id='unique-job-123')
356
print(f"Hashed expansion: {expanded}")
357
358
# Expand 6-field cron with seconds
359
expanded, _ = croniter.expand('*/30 */5 0-12 * * mon-fri', second_at_beginning=True)
360
print(f"6-field expansion: {expanded}")
361
```
362
363
### Static Method Usage
364
365
```python
366
from croniter import croniter
367
368
# Check leap years
369
print(croniter.is_leap(2024)) # True
370
print(croniter.is_leap(2023)) # False
371
372
# Convert month names
373
numeric_month = croniter.value_alias('jan', croniter.MONTH_FIELD)
374
print(numeric_month) # 1
375
376
# Convert day names
377
numeric_day = croniter.value_alias('mon', croniter.DOW_FIELD)
378
print(numeric_day) # 1
379
```