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

enum-extensions.mddocs/

0

# Enum Extensions

1

2

Enhanced functionality for `DayOfWeek` and `Month` enums including arithmetic operations, utility methods, and integration with other temporal types through operator overloading and factory methods.

3

4

## Capabilities

5

6

### DayOfWeek Operations

7

8

Enhanced functionality for the `DayOfWeek` enum with arithmetic and utility methods.

9

10

```groovy { .api }

11

/**

12

* Returns the DayOfWeek that is the specified number of days after this day.

13

*/

14

DayOfWeek plus(DayOfWeek self, int days)

15

16

/**

17

* Returns the DayOfWeek that is the specified number of days before this day.

18

*/

19

DayOfWeek minus(DayOfWeek self, int days)

20

21

/**

22

* Returns true if this day of the week is a weekend day (Saturday or Sunday).

23

*/

24

boolean isWeekend(DayOfWeek self)

25

26

/**

27

* Returns true if this day of the week is a weekday (Monday through Friday).

28

*/

29

boolean isWeekday(DayOfWeek self)

30

```

31

32

**Usage Examples:**

33

34

```groovy

35

import java.time.*

36

37

def monday = DayOfWeek.MONDAY

38

39

// Arithmetic operations

40

def wednesday = monday + 2 // Add 2 days -> WEDNESDAY

41

def saturday = monday + 5 // Add 5 days -> SATURDAY

42

def previousFriday = monday - 3 // Subtract 3 days -> FRIDAY

43

44

println "Monday + 2 days = ${wednesday}"

45

println "Monday + 5 days = ${saturday}"

46

println "Monday - 3 days = ${previousFriday}"

47

48

// Week wrapping

49

def sunday = DayOfWeek.SATURDAY + 1 // Wraps to SUNDAY

50

def friday = DayOfWeek.SUNDAY - 2 // Wraps to FRIDAY

51

52

println "Saturday + 1 = ${sunday}"

53

println "Sunday - 2 = ${friday}"

54

55

// Large numbers wrap around the week

56

def nextMonday = monday + 7 // 7 days later -> MONDAY

57

def sameDay = monday + 14 // 14 days later -> MONDAY

58

59

println "Monday + 7 days = ${nextMonday}"

60

println "Monday + 14 days = ${sameDay}"

61

62

// Weekend/weekday checking

63

def days = DayOfWeek.values()

64

days.each { day ->

65

def type = day.isWeekend() ? 'weekend' : 'weekday'

66

println "${day} is a ${type}"

67

}

68

69

// Practical usage

70

def today = LocalDate.now().dayOfWeek

71

if (today.isWeekday()) {

72

println "Today (${today}) is a work day"

73

} else {

74

println "Today (${today}) is a weekend"

75

}

76

77

// Find next business day

78

def nextBusinessDay = today

79

while (nextBusinessDay.isWeekend()) {

80

nextBusinessDay = nextBusinessDay + 1

81

}

82

println "Next business day after ${today}: ${nextBusinessDay}"

83

```

84

85

### Month Operations

86

87

Enhanced functionality for the `Month` enum with arithmetic operations and temporal object creation.

88

89

```groovy { .api }

90

/**

91

* Returns the Month that is the specified number of months after this month.

92

*/

93

Month plus(Month self, int months)

94

95

/**

96

* Returns the Month that is the specified number of months before this month.

97

*/

98

Month minus(Month self, int months)

99

100

/**

101

* Creates a MonthDay at the provided day of the month.

102

*/

103

MonthDay leftShift(Month self, int dayOfMonth)

104

105

/**

106

* Creates a YearMonth with the provided Year.

107

*/

108

YearMonth leftShift(Month self, Year year)

109

```

110

111

**Usage Examples:**

112

113

```groovy

114

import java.time.*

115

116

def january = Month.JANUARY

117

118

// Arithmetic operations

119

def march = january + 2 // Add 2 months -> MARCH

120

def november = january - 2 // Subtract 2 months -> NOVEMBER (wraps to previous year)

121

def april = january + 3 // Add 3 months -> APRIL

122

123

println "January + 2 months = ${march}"

124

println "January - 2 months = ${november}"

125

println "January + 3 months = ${april}"

126

127

// Year wrapping

128

def december = Month.JANUARY - 1 // Wraps to DECEMBER

129

def february = Month.DECEMBER + 2 // Wraps to FEBRUARY

130

131

println "January - 1 month = ${december}"

132

println "December + 2 months = ${february}"

133

134

// Large numbers wrap around

135

def sameMonth = january + 12 // 12 months later -> JANUARY

136

def nextJanuary = january + 13 // 13 months later -> FEBRUARY

137

138

println "January + 12 months = ${sameMonth}"

139

println "January + 13 months = ${nextJanuary}"

140

141

// Creating temporal objects using left shift operator

142

def newYearsEve = Month.DECEMBER << 31 // MonthDay: December 31st

143

def christmas = Month.DECEMBER << 25 // MonthDay: December 25th

144

def valentines = Month.FEBRUARY << 14 // MonthDay: February 14th

145

146

println "New Year's Eve: ${newYearsEve}"

147

println "Christmas: ${christmas}"

148

println "Valentine's Day: ${valentines}"

149

150

// Creating YearMonth objects

151

def currentYear = Year.now()

152

def januaryThisYear = Month.JANUARY << currentYear // YearMonth: January of current year

153

def december2024 = Month.DECEMBER << Year.of(2024) // YearMonth: December 2024

154

155

println "January this year: ${januaryThisYear}"

156

println "December 2024: ${december2024}"

157

158

// Practical usage - seasonal operations

159

def seasons = [

160

'Spring': [Month.MARCH, Month.APRIL, Month.MAY],

161

'Summer': [Month.JUNE, Month.JULY, Month.AUGUST],

162

'Fall': [Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER],

163

'Winter': [Month.DECEMBER, Month.JANUARY, Month.FEBRUARY]

164

]

165

166

def currentMonth = LocalDate.now().month

167

def currentSeason = seasons.find { season, months ->

168

months.contains(currentMonth)

169

}?.key

170

171

println "Current month ${currentMonth} is in ${currentSeason}"

172

173

// Working with month lengths

174

def year2024 = Year.of(2024)

175

Month.values().each { month ->

176

def monthLength = (month << year2024).lengthOfMonth()

177

println "${month}: ${monthLength} days in 2024"

178

}

179

```

180

181

### Integration with Temporal Objects

182

183

How enum extensions integrate with other temporal types for comprehensive date/time operations.

184

185

**Usage Examples:**

186

187

```groovy

188

import java.time.*

189

190

// Using DayOfWeek with LocalDate operations

191

def findNextOccurrence = { LocalDate startDate, DayOfWeek targetDay ->

192

def current = startDate

193

while (current.dayOfWeek != targetDay) {

194

current = current + 1

195

}

196

return current

197

}

198

199

def today = LocalDate.now()

200

def nextFriday = findNextOccurrence(today, DayOfWeek.FRIDAY)

201

def nextMonday = findNextOccurrence(today, DayOfWeek.MONDAY)

202

203

println "Next Friday: ${nextFriday}"

204

println "Next Monday: ${nextMonday}"

205

206

// Using Month with date creation

207

def createHolidays = { Year year ->

208

return [

209

'New Year': (Month.JANUARY << 1) << year, // January 1st

210

'Independence Day': (Month.JULY << 4) << year, // July 4th

211

'Christmas': (Month.DECEMBER << 25) << year // December 25th

212

]

213

}

214

215

def holidays2024 = createHolidays(Year.of(2024))

216

holidays2024.each { name, date ->

217

println "${name}: ${date} (${date.dayOfWeek})"

218

}

219

220

// Business day calculations

221

def isBusinessDay = { LocalDate date ->

222

return date.dayOfWeek.isWeekday()

223

}

224

225

def addBusinessDays = { LocalDate startDate, int businessDays ->

226

def current = startDate

227

def added = 0

228

229

while (added < businessDays) {

230

current = current + 1

231

if (isBusinessDay(current)) {

232

added++

233

}

234

}

235

return current

236

}

237

238

def startDate = LocalDate.of(2024, 12, 20) // Friday

239

def fiveDaysLater = addBusinessDays(startDate, 5)

240

241

println "5 business days after ${startDate}: ${fiveDaysLater}"

242

243

// Monthly reporting periods

244

def getQuarterMonths = { int quarter ->

245

def baseMonth = Month.JANUARY + ((quarter - 1) * 3)

246

return [

247

baseMonth,

248

baseMonth + 1,

249

baseMonth + 2

250

]

251

}

252

253

(1..4).each { quarter ->

254

def months = getQuarterMonths(quarter)

255

println "Q${quarter}: ${months.join(', ')}"

256

}

257

258

// Seasonal date ranges

259

def getSeason = { Month month ->

260

switch (month) {

261

case [Month.DECEMBER, Month.JANUARY, Month.FEBRUARY]:

262

return 'Winter'

263

case [Month.MARCH, Month.APRIL, Month.MAY]:

264

return 'Spring'

265

case [Month.JUNE, Month.JULY, Month.AUGUST]:

266

return 'Summer'

267

case [Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER]:

268

return 'Fall'

269

}

270

}

271

272

def currentMonth = LocalDate.now().month

273

def season = getSeason(currentMonth)

274

println "Current season for ${currentMonth}: ${season}"

275

276

// Weekend vs weekday analysis

277

def analyzeWeek = { LocalDate startOfWeek ->

278

def days = (0..6).collect { startOfWeek + it }

279

def weekdays = days.findAll { it.dayOfWeek.isWeekday() }

280

def weekends = days.findAll { it.dayOfWeek.isWeekend() }

281

282

return [

283

weekdays: weekdays,

284

weekends: weekends,

285

totalDays: days.size(),

286

workingDays: weekdays.size()

287

]

288

}

289

290

def monday = LocalDate.now().with(DayOfWeek.MONDAY) // Start of current week

291

def weekAnalysis = analyzeWeek(monday)

292

293

println "Week starting ${monday}:"

294

println "Working days: ${weekAnalysis.workingDays} (${weekAnalysis.weekdays.join(', ')})"

295

println "Weekend days: ${weekAnalysis.weekends.size()} (${weekAnalysis.weekends.join(', ')})"

296

```

297

298

### Enum Arithmetic Edge Cases

299

300

Understanding the behavior of enum arithmetic with edge cases and boundary conditions.

301

302

**Usage Examples:**

303

304

```groovy

305

import java.time.*

306

307

// DayOfWeek edge cases

308

def sunday = DayOfWeek.SUNDAY

309

310

// Negative arithmetic

311

def saturday = sunday - 1 // SATURDAY

312

def friday = sunday - 2 // FRIDAY

313

def monday = sunday - (-1) // Same as sunday + 1 -> MONDAY

314

315

// Large numbers

316

def stillSunday = sunday + 7 // Wraps around -> SUNDAY

317

def alsoSunday = sunday + 14 // Multiple weeks -> SUNDAY

318

def backToSunday = sunday - 7 // Negative wrap -> SUNDAY

319

320

println "Sunday - 1 = ${saturday}"

321

println "Sunday + 7 = ${stillSunday}"

322

println "Sunday - 7 = ${backToSunday}"

323

324

// Month edge cases

325

def december = Month.DECEMBER

326

327

// Crossing year boundaries

328

def january = december + 1 // Wraps to JANUARY

329

def november = december - 1 // NOVEMBER

330

def february = december + 2 // FEBRUARY (next year conceptually)

331

332

// Large arithmetic

333

def sameDecember = december + 12 // Full year -> DECEMBER

334

def march = december + 3 // MARCH (next year)

335

def september = december - 3 // SEPTEMBER (same year)

336

337

println "December + 1 = ${january}"

338

println "December + 12 = ${sameDecember}"

339

println "December - 3 = ${september}"

340

341

// Zero arithmetic (identity)

342

def unchangedDay = DayOfWeek.WEDNESDAY + 0 // WEDNESDAY

343

def unchangedMonth = Month.JUNE + 0 // JUNE

344

345

println "Wednesday + 0 = ${unchangedDay}"

346

println "June + 0 = ${unchangedMonth}"

347

348

// Modular arithmetic demonstration

349

def demonstrateModular = { DayOfWeek day, List<Integer> offsets ->

350

offsets.each { offset ->

351

def result = day + offset

352

println "${day} + ${offset} = ${result} (offset mod 7 = ${offset % 7})"

353

}

354

}

355

356

println "DayOfWeek modular arithmetic:"

357

demonstrateModular(DayOfWeek.MONDAY, [0, 1, 7, 8, 14, 15, -1, -7, -8])

358

359

// Month modular arithmetic

360

def demonstrateMonthModular = { Month month, List<Integer> offsets ->

361

offsets.each { offset ->

362

def result = month + offset

363

println "${month} + ${offset} = ${result} (offset mod 12 = ${offset % 12})"

364

}

365

}

366

367

println "\nMonth modular arithmetic:"

368

demonstrateMonthModular(Month.JANUARY, [0, 1, 12, 13, 24, 25, -1, -12, -13])

369

```

370

371

### Practical Applications

372

373

Real-world scenarios demonstrating the utility of enum extensions.

374

375

**Usage Examples:**

376

377

```groovy

378

import java.time.*

379

380

// Payroll system - find pay dates (every other Friday)

381

def calculatePayDates = { LocalDate startDate, int numberOfPays ->

382

def payDates = []

383

def current = startDate

384

385

// Find first Friday on or after start date

386

while (current.dayOfWeek != DayOfWeek.FRIDAY) {

387

current = current + 1

388

}

389

390

numberOfPays.times {

391

payDates << current

392

current = current + 14 // Every two weeks

393

}

394

395

return payDates

396

}

397

398

def payDates = calculatePayDates(LocalDate.of(2024, 1, 1), 6)

399

println "Pay dates for first half of 2024:"

400

payDates.each { date ->

401

println "${date} (${date.dayOfWeek})"

402

}

403

404

// Restaurant schedule - closed on Mondays, special menu on weekends

405

def getRestaurantStatus = { LocalDate date ->

406

def dayOfWeek = date.dayOfWeek

407

408

if (dayOfWeek == DayOfWeek.MONDAY) {

409

return 'Closed'

410

} else if (dayOfWeek.isWeekend()) {

411

return 'Special Weekend Menu'

412

} else {

413

return 'Regular Menu'

414

}

415

}

416

417

def thisWeek = (0..6).collect { LocalDate.now().with(DayOfWeek.MONDAY) + it }

418

println "Restaurant schedule this week:"

419

thisWeek.each { date ->

420

println "${date} (${date.dayOfWeek}): ${getRestaurantStatus(date)}"

421

}

422

423

// Seasonal product availability

424

def getProductAvailability = { Month month ->

425

def season = null

426

switch (month) {

427

case [Month.DECEMBER, Month.JANUARY, Month.FEBRUARY]:

428

season = 'Winter'

429

break

430

case [Month.MARCH, Month.APRIL, Month.MAY]:

431

season = 'Spring'

432

break

433

case [Month.JUNE, Month.JULY, Month.AUGUST]:

434

season = 'Summer'

435

break

436

case [Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER]:

437

season = 'Fall'

438

break

439

}

440

441

def products = [

442

'Winter': ['Hot chocolate', 'Soup', 'Winter coats'],

443

'Spring': ['Rain gear', 'Gardening supplies', 'Light jackets'],

444

'Summer': ['Sunscreen', 'Swimming gear', 'Ice cream'],

445

'Fall': ['Pumpkins', 'Warm sweaters', 'Back-to-school supplies']

446

]

447

448

return [season: season, products: products[season]]

449

}

450

451

Month.values().each { month ->

452

def availability = getProductAvailability(month)

453

println "${month} (${availability.season}): ${availability.products.join(', ')}"

454

}

455

456

// Meeting scheduler - avoid Mondays and Fridays

457

def findBestMeetingDay = { LocalDate weekStart ->

458

def preferredDays = [DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY]

459

def monday = weekStart.with(DayOfWeek.MONDAY)

460

461

def availableDays = preferredDays.collect { dayOfWeek ->

462

monday.with(dayOfWeek)

463

}

464

465

return availableDays.find { date ->

466

// Additional logic could check calendar conflicts, etc.

467

true // For demo, all preferred days are available

468

}

469

}

470

471

def nextWeek = LocalDate.now().plusWeeks(1)

472

def bestDay = findBestMeetingDay(nextWeek)

473

println "Best day for meeting next week: ${bestDay} (${bestDay.dayOfWeek})"

474

```