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

year-month-operations.mddocs/

0

# Year and YearMonth Operations

1

2

Functionality for working with Year and YearMonth temporal objects including arithmetic operations, period calculations, and temporal object creation through operator overloading.

3

4

## Capabilities

5

6

### Year Operations

7

8

Year represents a year in the ISO-8601 calendar system.

9

10

```groovy { .api }

11

/**

12

* Returns a Year that is the specified number of years after this year.

13

*/

14

Year plus(Year self, long years)

15

16

/**

17

* Returns a Year that is the specified number of years before this year.

18

*/

19

Year minus(Year self, long years)

20

21

/**

22

* Returns the next Year after this year.

23

*/

24

Year next(Year self)

25

26

/**

27

* Returns the previous Year before this year.

28

*/

29

Year previous(Year self)

30

31

/**

32

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

33

*/

34

Period rightShift(Year self, Year year)

35

36

/**

37

* Returns a YearMonth of this year and the provided Month.

38

*/

39

YearMonth leftShift(Year self, Month month)

40

41

/**

42

* Returns a LocalDate of this year on the given MonthDay.

43

*/

44

LocalDate leftShift(Year self, MonthDay monthDay)

45

46

/**

47

* Returns the era of the year (0 for BC, 1 for AD).

48

*/

49

int getEra(Year self)

50

51

/**

52

* Returns the year value of the era.

53

*/

54

int getYearOfEra(Year self)

55

```

56

57

**Usage Examples:**

58

59

```groovy

60

import java.time.*

61

62

def year2024 = Year.of(2024)

63

64

// Arithmetic operations

65

def nextYear = year2024 + 1 // Year 2025

66

def fiveYearsAgo = year2024 - 5 // Year 2019

67

def decade = year2024 + 10 // Year 2034

68

69

// Navigation

70

def following = year2024.next() // Year 2025

71

def preceding = year2024.previous() // Year 2023

72

73

// Period calculation

74

def period = year2024 >> Year.of(2030) // Period of 6 years

75

76

// Creating other temporal objects

77

def january2024 = year2024 << Month.JANUARY // YearMonth: 2024-01

78

def christmas = year2024 << MonthDay.of(12, 25) // LocalDate: 2024-12-25

79

def newYear = year2024 << MonthDay.of(1, 1) // LocalDate: 2024-01-01

80

81

// Era information

82

def era = year2024.era // 1 (AD/CE)

83

def yearOfEra = year2024.yearOfEra // 2024

84

85

// Practical examples

86

def isLeapYear = year2024.isLeap() // true (2024 is a leap year)

87

def daysInYear = year2024.length() // 366 (leap year)

88

89

// Working with leap years

90

def leapYears = (2020..2030).findAll { Year.of(it).isLeap() }

91

println "Leap years between 2020-2030: ${leapYears}" // [2020, 2024, 2028]

92

```

93

94

### YearMonth Operations

95

96

YearMonth represents a year-month combination in the ISO-8601 calendar system.

97

98

```groovy { .api }

99

/**

100

* Returns a YearMonth that is the specified number of months after this year-month.

101

*/

102

YearMonth plus(YearMonth self, long months)

103

104

/**

105

* Returns a YearMonth that is the specified number of months before this year-month.

106

*/

107

YearMonth minus(YearMonth self, long months)

108

109

/**

110

* Returns the next YearMonth after this year-month.

111

*/

112

YearMonth next(YearMonth self)

113

114

/**

115

* Returns the previous YearMonth before this year-month.

116

*/

117

YearMonth previous(YearMonth self)

118

119

/**

120

* Returns a LocalDate of this year-month and the given day of the month.

121

*/

122

LocalDate leftShift(YearMonth self, int dayOfMonth)

123

124

/**

125

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

126

*/

127

Period rightShift(YearMonth self, YearMonth other)

128

```

129

130

**Usage Examples:**

131

132

```groovy

133

import java.time.*

134

135

def dec2024 = YearMonth.of(2024, 12)

136

137

// Arithmetic operations

138

def nextMonth = dec2024 + 1 // YearMonth: 2025-01

139

def sixMonthsAgo = dec2024 - 6 // YearMonth: 2024-06

140

def twoYearsLater = dec2024 + 24 // YearMonth: 2026-12

141

142

// Navigation

143

def following = dec2024.next() // YearMonth: 2025-01

144

def preceding = dec2024.previous() // YearMonth: 2024-11

145

146

// Creating LocalDate with specific day

147

def christmas = dec2024 << 25 // LocalDate: 2024-12-25

148

def newYearsEve = dec2024 << 31 // LocalDate: 2024-12-31

149

def firstOfMonth = dec2024 << 1 // LocalDate: 2024-12-01

150

151

// Period calculation

152

def period = dec2024 >> YearMonth.of(2025, 6) // Period of 6 months

153

154

// Practical examples

155

def monthLength = dec2024.lengthOfMonth() // 31 days

156

def yearLength = dec2024.lengthOfYear() // 366 days (2024 is leap year)

157

158

// Generate date ranges for the month

159

def allDaysInMonth = (1..monthLength).collect { dec2024 << it }

160

println "All days in December 2024: ${allDaysInMonth.size()} days"

161

162

// Financial quarters

163

def getQuarter = { YearMonth yearMonth ->

164

def month = yearMonth.monthValue

165

return Math.ceil(month / 3.0) as int

166

}

167

168

def quarter = getQuarter(dec2024) // 4 (Q4)

169

println "December 2024 is in Q${quarter}"

170

171

// Month-end processing

172

def isMonthEnd = { LocalDate date ->

173

def yearMonth = YearMonth.from(date)

174

return date.dayOfMonth == yearMonth.lengthOfMonth()

175

}

176

177

def endOfDec = dec2024 << 31

178

println "Is ${endOfDec} month-end? ${isMonthEnd(endOfDec)}" // true

179

```

180

181

### MonthDay Operations

182

183

Enhanced functionality for MonthDay temporal objects.

184

185

```groovy { .api }

186

/**

187

* Returns a LocalDate of this month-day and the provided year.

188

*/

189

LocalDate leftShift(MonthDay self, int year)

190

191

/**

192

* Returns a LocalDate of this month-day and the provided Year.

193

*/

194

LocalDate leftShift(MonthDay self, Year year)

195

```

196

197

**Usage Examples:**

198

199

```groovy

200

import java.time.*

201

202

def christmas = MonthDay.of(12, 25)

203

def leapDay = MonthDay.of(2, 29)

204

205

// Creating LocalDate for specific years

206

def christmas2024 = christmas << 2024 // LocalDate: 2024-12-25

207

def christmas2025 = christmas << Year.of(2025) // LocalDate: 2025-12-25

208

209

// Working with leap day

210

def leapDay2024 = leapDay << Year.of(2024) // LocalDate: 2024-02-29

211

// Note: leapDay << 2023 would throw an exception (2023 is not a leap year)

212

213

// Holiday calculations

214

def holidays = [

215

'New Year': MonthDay.of(1, 1),

216

'Valentine\'s Day': MonthDay.of(2, 14),

217

'Christmas': MonthDay.of(12, 25)

218

]

219

220

def year = Year.of(2024)

221

holidays.each { name, monthDay ->

222

def date = monthDay << year

223

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

224

}

225

226

// Anniversary tracking

227

def anniversary = MonthDay.of(6, 15)

228

def thisYear = anniversary << Year.now()

229

def nextYear = anniversary << Year.now().plusYears(1)

230

231

println "This year's anniversary: ${thisYear}"

232

println "Next year's anniversary: ${nextYear}"

233

234

// Seasonal events

235

def seasons = [

236

'Spring Equinox': MonthDay.of(3, 20),

237

'Summer Solstice': MonthDay.of(6, 21),

238

'Fall Equinox': MonthDay.of(9, 22),

239

'Winter Solstice': MonthDay.of(12, 21)

240

]

241

242

def currentYear = Year.now()

243

seasons.each { event, monthDay ->

244

def date = monthDay << currentYear

245

def daysUntil = LocalDate.now().until(date, ChronoUnit.DAYS)

246

println "${event}: ${date} (${daysUntil} days away)"

247

}

248

```

249

250

### Integration with Other Temporal Types

251

252

How Year and YearMonth operations integrate with the broader datetime system.

253

254

**Usage Examples:**

255

256

```groovy

257

import java.time.*

258

import java.time.temporal.ChronoUnit

259

260

// Financial year calculations

261

def calculateFiscalYear = { LocalDate date ->

262

// Assuming fiscal year starts in April

263

def year = date.year

264

def fiscalYear = (date.monthValue >= 4) ? year : year - 1

265

return Year.of(fiscalYear)

266

}

267

268

def today = LocalDate.now()

269

def fiscalYear = calculateFiscalYear(today)

270

def fiscalStart = fiscalYear << MonthDay.of(4, 1)

271

def fiscalEnd = (fiscalYear + 1) << MonthDay.of(3, 31)

272

273

println "Current fiscal year: ${fiscalYear.value}"

274

println "Fiscal year period: ${fiscalStart} to ${fiscalEnd}"

275

276

// Age calculations

277

def calculateAge = { LocalDate birthDate, LocalDate asOfDate ->

278

def birthYear = Year.from(birthDate)

279

def currentYear = Year.from(asOfDate)

280

def yearsDiff = currentYear.value - birthYear.value

281

282

// Adjust if birthday hasn't occurred this year

283

def birthMonthDay = MonthDay.from(birthDate)

284

def currentMonthDay = MonthDay.from(asOfDate)

285

286

if (currentMonthDay.isBefore(birthMonthDay)) {

287

yearsDiff--

288

}

289

290

return yearsDiff

291

}

292

293

def birthDate = LocalDate.of(1990, 6, 15)

294

def age = calculateAge(birthDate, LocalDate.now())

295

println "Age: ${age} years"

296

297

// Project timeline management

298

def projectStart = YearMonth.of(2024, 3)

299

def projectDuration = 18 // months

300

301

def milestones = [:]

302

(0..projectDuration).step(3) { monthOffset ->

303

def milestone = projectStart + monthOffset

304

def quarter = "Q${Math.ceil(milestone.monthValue / 3.0) as int}"

305

milestones["${milestone.year} ${quarter}"] = milestone

306

}

307

308

println "Project milestones:"

309

milestones.each { quarter, yearMonth ->

310

println "${quarter}: ${yearMonth}"

311

}

312

313

// Seasonal business analysis

314

def analyzeSeason = { YearMonth yearMonth ->

315

def month = yearMonth.month

316

switch (month) {

317

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

318

return [season: 'Winter', category: 'Holiday/Indoor']

319

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

320

return [season: 'Spring', category: 'Renewal/Growth']

321

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

322

return [season: 'Summer', category: 'Vacation/Outdoor']

323

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

324

return [season: 'Fall', category: 'Back-to-School/Harvest']

325

}

326

}

327

328

def currentMonth = YearMonth.now()

329

def analysis = analyzeSeason(currentMonth)

330

println "Current month ${currentMonth}: ${analysis.season} (${analysis.category})"

331

332

// Lease and contract management

333

def calculateLeaseEnd = { LocalDate startDate, int durationMonths ->

334

def startYearMonth = YearMonth.from(startDate)

335

def endYearMonth = startYearMonth + durationMonths

336

// Use last day of the end month

337

return endYearMonth << endYearMonth.lengthOfMonth()

338

}

339

340

def leaseStart = LocalDate.of(2024, 1, 15)

341

def leaseEnd = calculateLeaseEnd(leaseStart, 12) // 12-month lease

342

println "Lease period: ${leaseStart} to ${leaseEnd}"

343

344

// Birthday and anniversary tracking

345

def findNextOccurrence = { MonthDay event, LocalDate fromDate ->

346

def thisYear = event << Year.from(fromDate)

347

def nextYear = event << Year.from(fromDate).plusYears(1)

348

349

return thisYear.isAfter(fromDate) ? thisYear : nextYear

350

}

351

352

def birthday = MonthDay.of(8, 22)

353

def nextBirthday = findNextOccurrence(birthday, LocalDate.now())

354

def daysUntil = ChronoUnit.DAYS.between(LocalDate.now(), nextBirthday)

355

356

println "Next birthday: ${nextBirthday} (${daysUntil} days away)"

357

```