CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-codehaus-groovy--groovy-datetime

Groovy extensions for working with Java 8+ date/time types, providing convenient methods for temporal operations and transformations

Pending
Overview
Eval results
Files

year-month-operations.mddocs/

Year and YearMonth Operations

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

Capabilities

Year Operations

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

/**
 * Returns a Year that is the specified number of years after this year.
 */
Year plus(Year self, long years)

/**
 * Returns a Year that is the specified number of years before this year.
 */
Year minus(Year self, long years)

/**
 * Returns the next Year after this year.
 */
Year next(Year self)

/**
 * Returns the previous Year before this year.
 */
Year previous(Year self)

/**
 * Returns a Period between the first day of this year and the first day of the provided Year.
 */
Period rightShift(Year self, Year year)

/**
 * Returns a YearMonth of this year and the provided Month.
 */
YearMonth leftShift(Year self, Month month)

/**
 * Returns a LocalDate of this year on the given MonthDay.
 */
LocalDate leftShift(Year self, MonthDay monthDay)

/**
 * Returns the era of the year (0 for BC, 1 for AD).
 */
int getEra(Year self)

/**
 * Returns the year value of the era.
 */
int getYearOfEra(Year self)

Usage Examples:

import java.time.*

def year2024 = Year.of(2024)

// Arithmetic operations
def nextYear = year2024 + 1        // Year 2025
def fiveYearsAgo = year2024 - 5    // Year 2019
def decade = year2024 + 10         // Year 2034

// Navigation
def following = year2024.next()     // Year 2025
def preceding = year2024.previous() // Year 2023

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

// Creating other temporal objects
def january2024 = year2024 << Month.JANUARY      // YearMonth: 2024-01
def christmas = year2024 << MonthDay.of(12, 25)  // LocalDate: 2024-12-25
def newYear = year2024 << MonthDay.of(1, 1)      // LocalDate: 2024-01-01

// Era information
def era = year2024.era                // 1 (AD/CE)
def yearOfEra = year2024.yearOfEra    // 2024

// Practical examples
def isLeapYear = year2024.isLeap()    // true (2024 is a leap year)
def daysInYear = year2024.length()    // 366 (leap year)

// Working with leap years
def leapYears = (2020..2030).findAll { Year.of(it).isLeap() }
println "Leap years between 2020-2030: ${leapYears}"  // [2020, 2024, 2028]

YearMonth Operations

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

/**
 * Returns a YearMonth that is the specified number of months after this year-month.
 */
YearMonth plus(YearMonth self, long months)

/**
 * Returns a YearMonth that is the specified number of months before this year-month.
 */
YearMonth minus(YearMonth self, long months)

/**
 * Returns the next YearMonth after this year-month.
 */
YearMonth next(YearMonth self)

/**
 * Returns the previous YearMonth before this year-month.
 */
YearMonth previous(YearMonth self)

/**
 * Returns a LocalDate of this year-month and the given day of the month.
 */
LocalDate leftShift(YearMonth self, int dayOfMonth)

/**
 * Returns a Period between the first day of this year-month and the given YearMonth.
 */
Period rightShift(YearMonth self, YearMonth other)

Usage Examples:

import java.time.*

def dec2024 = YearMonth.of(2024, 12)

// Arithmetic operations
def nextMonth = dec2024 + 1      // YearMonth: 2025-01
def sixMonthsAgo = dec2024 - 6   // YearMonth: 2024-06
def twoYearsLater = dec2024 + 24 // YearMonth: 2026-12

// Navigation
def following = dec2024.next()     // YearMonth: 2025-01
def preceding = dec2024.previous() // YearMonth: 2024-11

// Creating LocalDate with specific day
def christmas = dec2024 << 25      // LocalDate: 2024-12-25
def newYearsEve = dec2024 << 31    // LocalDate: 2024-12-31
def firstOfMonth = dec2024 << 1    // LocalDate: 2024-12-01

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

// Practical examples
def monthLength = dec2024.lengthOfMonth()  // 31 days
def yearLength = dec2024.lengthOfYear()    // 366 days (2024 is leap year)

// Generate date ranges for the month
def allDaysInMonth = (1..monthLength).collect { dec2024 << it }
println "All days in December 2024: ${allDaysInMonth.size()} days"

// Financial quarters
def getQuarter = { YearMonth yearMonth ->
    def month = yearMonth.monthValue
    return Math.ceil(month / 3.0) as int
}

def quarter = getQuarter(dec2024)  // 4 (Q4)
println "December 2024 is in Q${quarter}"

// Month-end processing
def isMonthEnd = { LocalDate date ->
    def yearMonth = YearMonth.from(date)
    return date.dayOfMonth == yearMonth.lengthOfMonth()
}

def endOfDec = dec2024 << 31
println "Is ${endOfDec} month-end? ${isMonthEnd(endOfDec)}"  // true

MonthDay Operations

Enhanced functionality for MonthDay temporal objects.

/**
 * Returns a LocalDate of this month-day and the provided year.
 */
LocalDate leftShift(MonthDay self, int year)

/**
 * Returns a LocalDate of this month-day and the provided Year.
 */
LocalDate leftShift(MonthDay self, Year year)

Usage Examples:

import java.time.*

def christmas = MonthDay.of(12, 25)
def leapDay = MonthDay.of(2, 29)

// Creating LocalDate for specific years
def christmas2024 = christmas << 2024        // LocalDate: 2024-12-25
def christmas2025 = christmas << Year.of(2025) // LocalDate: 2025-12-25

// Working with leap day
def leapDay2024 = leapDay << Year.of(2024)   // LocalDate: 2024-02-29
// Note: leapDay << 2023 would throw an exception (2023 is not a leap year)

// Holiday calculations
def holidays = [
    'New Year': MonthDay.of(1, 1),
    'Valentine\'s Day': MonthDay.of(2, 14),
    'Christmas': MonthDay.of(12, 25)
]

def year = Year.of(2024)
holidays.each { name, monthDay ->
    def date = monthDay << year
    println "${name} in ${year.value}: ${date} (${date.dayOfWeek})"
}

// Anniversary tracking
def anniversary = MonthDay.of(6, 15)
def thisYear = anniversary << Year.now()
def nextYear = anniversary << Year.now().plusYears(1)

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

// Seasonal events
def seasons = [
    'Spring Equinox': MonthDay.of(3, 20),
    'Summer Solstice': MonthDay.of(6, 21),
    'Fall Equinox': MonthDay.of(9, 22),
    'Winter Solstice': MonthDay.of(12, 21)
]

def currentYear = Year.now()
seasons.each { event, monthDay ->
    def date = monthDay << currentYear
    def daysUntil = LocalDate.now().until(date, ChronoUnit.DAYS)
    println "${event}: ${date} (${daysUntil} days away)"
}

Integration with Other Temporal Types

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

Usage Examples:

import java.time.*
import java.time.temporal.ChronoUnit

// Financial year calculations
def calculateFiscalYear = { LocalDate date ->
    // Assuming fiscal year starts in April
    def year = date.year
    def fiscalYear = (date.monthValue >= 4) ? year : year - 1
    return Year.of(fiscalYear)
}

def today = LocalDate.now()
def fiscalYear = calculateFiscalYear(today)
def fiscalStart = fiscalYear << MonthDay.of(4, 1)
def fiscalEnd = (fiscalYear + 1) << MonthDay.of(3, 31)

println "Current fiscal year: ${fiscalYear.value}"
println "Fiscal year period: ${fiscalStart} to ${fiscalEnd}"

// Age calculations
def calculateAge = { LocalDate birthDate, LocalDate asOfDate ->
    def birthYear = Year.from(birthDate)
    def currentYear = Year.from(asOfDate)
    def yearsDiff = currentYear.value - birthYear.value
    
    // Adjust if birthday hasn't occurred this year
    def birthMonthDay = MonthDay.from(birthDate)
    def currentMonthDay = MonthDay.from(asOfDate)
    
    if (currentMonthDay.isBefore(birthMonthDay)) {
        yearsDiff--
    }
    
    return yearsDiff
}

def birthDate = LocalDate.of(1990, 6, 15)
def age = calculateAge(birthDate, LocalDate.now())
println "Age: ${age} years"

// Project timeline management
def projectStart = YearMonth.of(2024, 3)
def projectDuration = 18  // months

def milestones = [:]
(0..projectDuration).step(3) { monthOffset ->
    def milestone = projectStart + monthOffset
    def quarter = "Q${Math.ceil(milestone.monthValue / 3.0) as int}"
    milestones["${milestone.year} ${quarter}"] = milestone
}

println "Project milestones:"
milestones.each { quarter, yearMonth ->
    println "${quarter}: ${yearMonth}"
}

// Seasonal business analysis
def analyzeSeason = { YearMonth yearMonth ->
    def month = yearMonth.month
    switch (month) {
        case [Month.DECEMBER, Month.JANUARY, Month.FEBRUARY]:
            return [season: 'Winter', category: 'Holiday/Indoor']
        case [Month.MARCH, Month.APRIL, Month.MAY]:
            return [season: 'Spring', category: 'Renewal/Growth']
        case [Month.JUNE, Month.JULY, Month.AUGUST]:
            return [season: 'Summer', category: 'Vacation/Outdoor']
        case [Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER]:
            return [season: 'Fall', category: 'Back-to-School/Harvest']
    }
}

def currentMonth = YearMonth.now()
def analysis = analyzeSeason(currentMonth)
println "Current month ${currentMonth}: ${analysis.season} (${analysis.category})"

// Lease and contract management
def calculateLeaseEnd = { LocalDate startDate, int durationMonths ->
    def startYearMonth = YearMonth.from(startDate)
    def endYearMonth = startYearMonth + durationMonths
    // Use last day of the end month
    return endYearMonth << endYearMonth.lengthOfMonth()
}

def leaseStart = LocalDate.of(2024, 1, 15)
def leaseEnd = calculateLeaseEnd(leaseStart, 12)  // 12-month lease
println "Lease period: ${leaseStart} to ${leaseEnd}"

// Birthday and anniversary tracking
def findNextOccurrence = { MonthDay event, LocalDate fromDate ->
    def thisYear = event << Year.from(fromDate)
    def nextYear = event << Year.from(fromDate).plusYears(1)
    
    return thisYear.isAfter(fromDate) ? thisYear : nextYear
}

def birthday = MonthDay.of(8, 22)
def nextBirthday = findNextOccurrence(birthday, LocalDate.now())
def daysUntil = ChronoUnit.DAYS.between(LocalDate.now(), nextBirthday)

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

Install with Tessl CLI

npx tessl i tessl/maven-org-codehaus-groovy--groovy-datetime

docs

date-time-operations.md

duration-period-operations.md

enum-extensions.md

index.md

legacy-conversion.md

parsing-factory-methods.md

temporal-iteration.md

year-month-operations.md

zone-offset-operations.md

tile.json