or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

date-time-operations.mdduration-period-operations.mdenum-extensions.mdindex.mdlegacy-conversion.mdparsing-factory-methods.mdtemporal-iteration.mdyear-month-operations.mdzone-offset-operations.md

temporal-iteration.mddocs/

0

# Temporal Iteration

1

2

Functionality for iterating over temporal ranges with support for custom units, step sizes, and calculating periods or durations between temporal objects.

3

4

## Capabilities

5

6

### Temporal Iteration Methods

7

8

Core iteration functionality that works with all Temporal subtypes.

9

10

```groovy { .api }

11

/**

12

* Iterates from this to the target Temporal, inclusive, incrementing by one default unit each iteration.

13

* Default units: DAYS for dates, MONTHS for YearMonth, YEARS for Year, SECONDS for others.

14

*/

15

void upto(Temporal from, Temporal to, Closure closure)

16

17

/**

18

* Iterates from this to the target Temporal, inclusive, incrementing by one specified unit each iteration.

19

*/

20

void upto(Temporal from, Temporal to, TemporalUnit unit, Closure closure)

21

22

/**

23

* Iterates from this to the target Temporal, inclusive, decrementing by one default unit each iteration.

24

*/

25

void downto(Temporal from, Temporal to, Closure closure)

26

27

/**

28

* Iterates from this to the target Temporal, inclusive, decrementing by one specified unit each iteration.

29

*/

30

void downto(Temporal from, Temporal to, TemporalUnit unit, Closure closure)

31

32

/**

33

* Returns a TemporalAmount (Duration or Period) between this and another Temporal.

34

* Returns Period for dates, Duration for times.

35

*/

36

TemporalAmount rightShift(Temporal self, Temporal other)

37

```

38

39

### TemporalAccessor Operations

40

41

Generic field access operations for all temporal objects that implement TemporalAccessor.

42

43

```groovy { .api }

44

/**

45

* Supports the subscript operator for accessing temporal fields.

46

* Equivalent to calling getLong(TemporalField).

47

*/

48

long getAt(TemporalAccessor self, TemporalField field)

49

```

50

51

### TemporalAmount Operations

52

53

Generic unit access operations for temporal amounts (Duration and Period).

54

55

```groovy { .api }

56

/**

57

* Supports the subscript operator for accessing temporal units.

58

* Equivalent to calling get(TemporalUnit).

59

*/

60

long getAt(TemporalAmount self, TemporalUnit unit)

61

```

62

63

**Usage Examples:**

64

65

```groovy

66

import java.time.*

67

import java.time.temporal.ChronoUnit

68

import java.time.temporal.ChronoField

69

70

// Date iteration with default unit (days)

71

def start = LocalDate.of(2024, 1, 1)

72

def end = start + 5

73

start.upto(end) { date ->

74

println "${date} is ${date.dayOfWeek}"

75

}

76

77

// Date iteration with custom unit

78

start.upto(end, ChronoUnit.DAYS) { date ->

79

println "Processing: ${date}"

80

}

81

82

// Time iteration (default unit is seconds)

83

def startTime = LocalTime.of(10, 0)

84

def endTime = startTime + 5 // 5 seconds later

85

startTime.upto(endTime) { time ->

86

println time

87

}

88

89

// Year iteration (default unit is years)

90

def startYear = Year.of(2020)

91

def endYear = Year.of(2024)

92

startYear.upto(endYear) { year ->

93

println "Year: ${year.value}"

94

}

95

96

// Downto iteration

97

end.downto(start) { date ->

98

println "Counting down: ${date}"

99

}

100

101

// Period calculation using right shift operator

102

def period = start >> end // Returns Period

103

println "Period: ${period.days} days"

104

105

// Duration calculation

106

def duration = startTime >> endTime // Returns Duration

107

println "Duration: ${duration.seconds} seconds"

108

109

// TemporalAccessor field access using subscript operator

110

def now = LocalDateTime.now()

111

def hourOfDay = now[ChronoField.HOUR_OF_DAY] // Get hour field

112

def dayOfYear = now[ChronoField.DAY_OF_YEAR] // Get day of year

113

def month = now[ChronoField.MONTH_OF_YEAR] // Get month

114

115

println "Current time: ${now}"

116

println "Hour of day: ${hourOfDay}"

117

println "Day of year: ${dayOfYear}"

118

println "Month: ${month}"

119

120

// TemporalAmount unit access using subscript operator

121

def period = Period.of(2, 3, 15) // 2 years, 3 months, 15 days

122

def years = period[ChronoUnit.YEARS] // Get years component

123

def months = period[ChronoUnit.MONTHS] // Get months component

124

def days = period[ChronoUnit.DAYS] // Get days component

125

126

println "Period: ${period}"

127

println "Years: ${years}"

128

println "Months: ${months}"

129

println "Days: ${days}"

130

131

def duration2 = Duration.ofHours(5).plusMinutes(30)

132

def hours = duration2[ChronoUnit.HOURS] // Get hours component

133

def minutes = duration2[ChronoUnit.MINUTES] // Get total minutes

134

135

println "Duration: ${duration2}"

136

println "Total hours: ${hours}"

137

println "Total minutes: ${minutes}"

138

```

139

140

### Date Range Iteration

141

142

Specialized iteration methods for date-based temporal types.

143

144

```groovy { .api }

145

/**

146

* Returns a LocalDate one day after this date.

147

*/

148

LocalDate next(LocalDate self)

149

150

/**

151

* Returns a LocalDate one day before this date.

152

*/

153

LocalDate previous(LocalDate self)

154

155

/**

156

* Returns a Period between this date and another date.

157

*/

158

Period rightShift(LocalDate self, LocalDate other)

159

```

160

161

**Usage Examples:**

162

163

```groovy

164

import java.time.*

165

166

def today = LocalDate.now()

167

def dates = []

168

169

// Collect dates using next() method

170

def current = today

171

5.times {

172

dates << current

173

current = current.next()

174

}

175

176

// Create date ranges for iteration

177

def startDate = LocalDate.of(2024, 1, 1)

178

def endDate = LocalDate.of(2024, 1, 7)

179

180

// Standard Groovy range operator works with dates

181

(startDate..endDate).each { date ->

182

println "${date}: ${date.dayOfWeek}"

183

}

184

185

// Calculate period between dates

186

def period = startDate >> endDate

187

println "Difference: ${period.days} days"

188

```

189

190

### Year and Month Iteration

191

192

Iteration support for year and month-based temporal types.

193

194

```groovy { .api }

195

/**

196

* Returns a Year one year after this year.

197

*/

198

Year next(Year self)

199

200

/**

201

* Returns a Year one year before this year.

202

*/

203

Year previous(Year self)

204

205

/**

206

* Returns a Period between the first day of this year and the first day of the target year.

207

*/

208

Period rightShift(Year self, Year other)

209

210

/**

211

* Returns a YearMonth one month after this year-month.

212

*/

213

YearMonth next(YearMonth self)

214

215

/**

216

* Returns a YearMonth one month before this year-month.

217

*/

218

YearMonth previous(YearMonth self)

219

220

/**

221

* Returns a Period between the first day of this year-month and the first day of the target year-month.

222

*/

223

Period rightShift(YearMonth self, YearMonth other)

224

```

225

226

**Usage Examples:**

227

228

```groovy

229

import java.time.*

230

231

// Year iteration

232

def startYear = Year.of(2020)

233

def endYear = Year.of(2024)

234

235

startYear.upto(endYear) { year ->

236

println "Processing year: ${year.value}"

237

println "Leap year: ${year.isLeap()}"

238

}

239

240

// YearMonth iteration

241

def startMonth = YearMonth.of(2024, 1)

242

def endMonth = YearMonth.of(2024, 6)

243

244

startMonth.upto(endMonth) { yearMonth ->

245

println "${yearMonth.month} ${yearMonth.year}: ${yearMonth.lengthOfMonth()} days"

246

}

247

248

// Calculate periods

249

def yearPeriod = startYear >> endYear

250

def monthPeriod = startMonth >> endMonth

251

println "Years between: ${yearPeriod.years}"

252

println "Months between: ${monthPeriod.months}"

253

```

254

255

### Custom Unit Iteration

256

257

Advanced iteration with custom temporal units and step sizes.

258

259

**Usage Examples:**

260

261

```groovy

262

import java.time.*

263

import java.time.temporal.ChronoUnit

264

265

def start = LocalDateTime.of(2024, 1, 1, 0, 0)

266

def end = start.plusDays(2)

267

268

// Iterate by hours

269

start.upto(end, ChronoUnit.HOURS) { dateTime ->

270

println dateTime.format('yyyy-MM-dd HH:mm')

271

}

272

273

// Iterate by 6-hour increments (not directly supported, but can be achieved)

274

def current = start

275

while (current <= end) {

276

println current.format('yyyy-MM-dd HH:mm')

277

current = current.plus(6, ChronoUnit.HOURS)

278

}

279

280

// Week-based iteration

281

def monday = LocalDate.of(2024, 1, 1) // Assume this is a Monday

282

def endOfMonth = LocalDate.of(2024, 1, 31)

283

284

monday.upto(endOfMonth, ChronoUnit.WEEKS) { date ->

285

println "Week starting: ${date}"

286

}

287

```

288

289

### Range Operators and Integration

290

291

Integration with Groovy's range operators for natural iteration syntax.

292

293

**Usage Examples:**

294

295

```groovy

296

import java.time.*

297

298

def start = LocalDate.of(2024, 1, 1)

299

def end = start + 10

300

301

// Using Groovy range operator (works because of next/previous methods)

302

(start..end).each { date ->

303

if (date.dayOfWeek == DayOfWeek.SUNDAY) {

304

println "Sunday: ${date}"

305

}

306

}

307

308

// Using step with ranges (for every other day)

309

(start..end).step(2) { date ->

310

println "Every other day: ${date}"

311

}

312

313

// Reverse ranges

314

(end..start).each { date ->

315

println "Counting down: ${date}"

316

}

317

```

318

319

### Error Handling and Constraints

320

321

Important behavior and limitations for temporal iteration.

322

323

**Exceptions Thrown:**

324

325

- `GroovyRuntimeException` - If the start value is later than the end value for `upto()`

326

- `GroovyRuntimeException` - If the start value is earlier than the end value for `downto()`

327

- `GroovyRuntimeException` - If the temporal types don't match

328

- `GroovyRuntimeException` - If temporal type doesn't support the specified unit

329

330

**Usage Examples:**

331

332

```groovy

333

import java.time.*

334

335

def start = LocalDate.of(2024, 1, 5)

336

def end = LocalDate.of(2024, 1, 1) // Earlier than start

337

338

try {

339

// This will throw GroovyRuntimeException

340

start.upto(end) { date ->

341

println date

342

}

343

} catch (GroovyRuntimeException e) {

344

println "Cannot iterate backwards with upto(): ${e.message}"

345

}

346

347

// Use downto() instead

348

start.downto(end) { date ->

349

println "Going backwards: ${date}"

350

}

351

352

// Type mismatch will also cause errors

353

def date = LocalDate.now()

354

def time = LocalTime.now()

355

356

try {

357

// This will throw GroovyRuntimeException

358

date.upto(time) { /* won't work */ }

359

} catch (GroovyRuntimeException e) {

360

println "Type mismatch: ${e.message}"

361

}

362

```