or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-iteration.mdindex.mdrange-operations.mdvalidation-matching.md

core-iteration.mddocs/

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

```