Class DateUtil

java.lang.Object
com.ssgllc.fish.service.util.registered.DateUtil

@Component public final class DateUtil extends Object
Date and time helpers: conversion between the date types in play, formatting, parsing, arithmetic, comparison, and epidemiological (MMWR) week numbering.

Three things are worth knowing before using this class.

Prefer f().date and f().instant for new work. The f() API is the current expression surface and is consistent about zones and nulls; much of this class predates it, and the string-based families here are deprecated.

The comparison helpers return true when either argument is null. beforeToday(null) is true, not false. Guard for null separately where that matters. compareDate(Instant, Instant) is the exception and throws instead.

Zones are implicit. Anything converting between a date and an instant uses the system default zone unless stated otherwise, so a value that crosses a system boundary can land on the adjacent day - see setTimeToNoon(Date). The *Patterned and *Str helpers additionally depend on the configured casetivity.dateFormat, which is why they are deprecated in favour of parsing to a LocalDate first.

  • Field Details

    • DEFAULT_DATE_PATTERN

      public static String DEFAULT_DATE_PATTERN
  • Method Details

    • setDatabase

      @Value("${casetivity.dateFormat}") public void setDatabase(String dateFormat)
      Spring wiring, not scripting API. Despite the name it sets no database - it captures casetivity.dateFormat into DEFAULT_DATE_PATTERN, the pattern the *Patterned and *Str helpers use. Never call this from a script.
    • getLocalDateFromJodaDate

      public static LocalDate getLocalDateFromJodaDate(Object jodaDate)
      Converts a Joda LocalDate to a LocalDate. Strictly typed: anything that is not exactly a Joda LocalDate yields null rather than an error, so this is safe to chain. For an input of unknown type use getLocalDateFromObject(Object).
      Parameters:
      jodaDate - the value to convert
      Returns:
      the equivalent LocalDate, or null if the input is not a Joda date

      Groovy example:
      return dateUtil.getLocalDateFromJodaDate(legacyDate)

      Returns:
      the same calendar day as a java.time.LocalDate
    • getLocalDateFromInstant

      public static LocalDate getLocalDateFromInstant(Object instantObj)
      Converts an Instant to the calendar date it falls on in the system default zone. The zone matters: an instant just before midnight UTC is the previous day in a behind-UTC zone. Anything that is not exactly an Instant yields null.
      Parameters:
      instantObj - the value to convert
      Returns:
      the local calendar date, or null if the input is not an Instant

      Groovy example:
      return dateUtil.getLocalDateFromInstant(entity.createdDate)

      Returns:
      the calendar day the record was created, in the server zone

      SpEL example:
      #getLocalDateFromInstant(#createdDate)

      Returns:
      2026-08-21
    • getLocalDateFromDate

      public static LocalDate getLocalDateFromDate(Object date)
      Converts a Date to the calendar date it falls on in the system default zone. Anything that is not exactly a Date yields null.
      Parameters:
      date - the value to convert
      Returns:
      the local calendar date, or null if the input is not a Date

      Groovy example:
      return dateUtil.getLocalDateFromDate(row.legacyTimestamp)

      Returns:
      the calendar day, in the server zone
    • getDate

      public static Date getDate(Object date)
      Converts the given object into a Date object. This method attempts to interpret the input object as a valid date representation and convert it into a Date. The supported input types are:
      • Date - Returns the input as is.
      • LocalDate - Converts to a Date using the system's default timezone.
      • LocalDate - Converts to a Date using the system's default timezone.
      • Instant - Converts to a Date preserving the UTC representation.
      • String - Attempts to parse the string into a Date, assuming it is in the default date format or ISO-8601.
      • Long - Treats the long value as an epoch timestamp in milliseconds.
      Note: For string inputs, the behavior may vary depending on the format and timezone assumptions. Strings like "2024-12-13" will typically be treated as UTC midnight by default. When using this method with strings, ensure you provide input consistent with the expected behavior. If your input string is not in UTC, consider using getDate(getLocalDate(string)) to handle timezone correctly.
      Parameters:
      date - the object to convert to a Date, or null
      Returns:
      the resulting Date, or null if the input could not be converted
    • getDateFromInstant

      public static Date getDateFromInstant(Object instantObj)
      Converts an Instant to a Date, preserving the instant exactly. Anything that is not exactly an Instant yields null.
      Parameters:
      instantObj - the value to convert
      Returns:
      the equivalent Date, or null if the input is not an Instant

      Groovy example:
      return dateUtil.getDateFromInstant(entity.createdDate)

      Returns:
      the same moment as a java.util.Date
    • getDateFromLocalDate

      public static Date getDateFromLocalDate(Object localDate)
      Converts a LocalDate to a Date at start of day in the system default zone. Anything that is not exactly a LocalDate yields null. Where the result crosses a system boundary, consider setTimeToNoon(Date) so a zone shift cannot move it to the adjacent day.
      Parameters:
      localDate - the value to convert
      Returns:
      midnight on that date in the server zone, or null if the input is not a LocalDate

      Groovy example:
      return dateUtil.getDateFromLocalDate(entity.birthDate)

      Returns:
      midnight on the birth date, in the server zone
    • setTimeToNoon

      public static Date setTimeToNoon(Date date)
      Moves a Date's time to 12:00:00.000 local, keeping the calendar day. A date stored at midnight lands on the previous day once it is read in a zone behind the writer's; noon leaves twelve hours of slack in each direction, which is enough for every US zone. Use it for date-only values that will cross zones.
      Parameters:
      date - the value to adjust
      Returns:
      the same day at local noon, or null if date is null

      Groovy example:
      return dateUtil.setTimeToNoon(dateUtil.getDate(entity.birthDate))

      Returns:
      the birth date at noon, safe to compare across US time zones
    • getDateFromJodaDate

      public static Date getDateFromJodaDate(Object jodaDate)
      Converts a Joda LocalDate to a Date at start of day in the system default zone. Anything that is not a Joda LocalDate yields null.
      Parameters:
      jodaDate - the value to convert
      Returns:
      the equivalent Date, or null if the input is not a Joda date

      Groovy example:
      return dateUtil.getDateFromJodaDate(legacyDate)

      Returns:
      the equivalent java.util.Date
    • isDate

      public static boolean isDate(Object date)
      Whether a value is one of the date types this class understands - LocalDate, a Joda LocalDate, a Date, or an f() plain date. A date-formatted String is not a date by this test, and neither is an Instant; use isStringValidDate(String, String) for strings.
      Parameters:
      date - the value to test
      Returns:
      true if the value is a recognised date type

      Groovy example:
      return dateUtil.isDate(row.value)

      Returns:
      false for the string "01/15/2026", true for a LocalDate

      SpEL example:
      #isDate(#value)

      Returns:
      true only for an actual date object
    • getLocalDate

      public static LocalDate getLocalDate(Object date)
      Coerces any supported value to a LocalDate. An alias for getLocalDateFromObject(Object) - see that method for the accepted types and the string-parsing rules.
      Parameters:
      date - the value to convert
      Returns:
      the calendar date, or null if it could not be interpreted

      Groovy example:
      return dateUtil.getLocalDate("01/15/2026")

      Returns:
      2026-01-15

      SpEL example:
      #getLocalDate(#anyDateValue)

      Returns:
      the value as a LocalDate
    • getLocalDateFromObject

      public static LocalDate getLocalDateFromObject(Object date)
      Coerces any supported value to a LocalDate, trying each type in turn. Accepts a LocalDate, Date, Joda LocalDate, Instant, an f() plain date, a String, or epoch milliseconds as a Long or numeric String.

      String parsing is by shape, not by a supplied pattern: longer than ten characters is parsed as an instant, a ten-character string containing - as yyyy-MM-dd, and anything else with the application's configured pattern (default MM/dd/yyyy). A value that matches nothing yields null rather than an error, so a null means "could not interpret" - pass a known pattern to getDateFromString(String, String) when a parse failure should be visible.

      Parameters:
      date - the value to convert
      Returns:
      the calendar date, or null if it could not be interpreted

      Groovy example:
      return dateUtil.getLocalDateFromObject(row.casetivityExtraFields['birthDate'])

      Returns:
      the date, whatever type or format the import produced
    • getStringFromDate

      public static String getStringFromDate(Object date, String format)
      Formats any supported date value with the given pattern. The input is coerced through getLocalDateFromObject(Object) first, so this both parses and formats - it is the usual way to restate a date in another format.
      Parameters:
      date - the value to format
      format - the output pattern, e.g. "yyyy-MM-dd"
      Returns:
      the formatted date, or null if the input could not be interpreted

      Groovy example:
      return dateUtil.getStringFromDate(entity.birthDate, "MM/dd/yyyy")

      Returns:
      "01/15/2026"

      SpEL example:
      #getStringFromDate(#birthDate, 'yyyy-MM-dd')

      Returns:
      "2026-01-15"
    • getDateFromStringObject

      public static LocalDate getDateFromStringObject(Object date)
      Parses a String to a LocalDate by inspecting its shape, with no pattern supplied. Longer than ten characters is treated as an instant; a ten-character string containing - as yyyy-MM-dd; anything else with the application's configured pattern (default MM/dd/yyyy). A non-String input yields null.

      Unlike most of this class this throws on a string it recognises the shape of but cannot parse. Prefer getDateFromString(String, String) when the format is known.

      Parameters:
      date - the value to parse
      Returns:
      the calendar date, or null if the input is not a String
      Throws:
      DateTimeParseException - if the string's shape matches but its content does not parse

      Groovy example:
      return dateUtil.getDateFromStringObject("2026-01-15")

      Returns:
      2026-01-15
    • getDateFromString

      public static LocalDate getDateFromString(String date, String format)
      Parses a String to a LocalDate with an explicit pattern. Fails loudly on a value that does not match, which is what you want when validating input; use isStringValidDate(String, String) to test first, or getLocalDateFromObject(Object) to guess the format.
      Parameters:
      date - the value to parse
      format - the pattern the value is expected to be in
      Returns:
      the calendar date, or null if date is null
      Throws:
      DateTimeParseException - if the value does not match format

      Groovy example:
      return dateUtil.getDateFromString("01/15/2026", "MM/dd/yyyy")

      Returns:
      2026-01-15

      SpEL example:
      #getDateFromString(#dobString, 'MM/dd/yyyy')

      Returns:
      the parsed date
    • isStringValidDate

      public static boolean isStringValidDate(String date, String format)
      Checks if a given string can be parsed into a date using the specified format.
      Parameters:
      date - The date string to validate.
      format - The date format pattern.
      Returns:
      true if parsing succeeds; false otherwise.

      Groovy example:
      return dateUtil.isStringValidDate("2025-07-02", "yyyy-MM-dd")

      Returns:
      true

      SpEL example:
      #isStringValidDate("2025-07-02", "yyyy-MM-dd")

      Returns:
      true

      Note: If date is null or cannot be parsed according to format, this method returns false.
    • isStringValidDateStrict

      public static boolean isStringValidDateStrict(String date, String format)
      Checks if a given string strictly matches the specified date format, rejecting “smart” adjustments (e.g., non-leap-year February 29).
      Uses ResolverStyle.STRICT to enforce exact date matching.
      Note: the year pattern should be uuuu instead of yyyy, because y represents “year-of-era” and expects an era designator (e.g., AD/BC).
      Parameters:
      date - The date string to validate.
      format - The date format pattern to enforce.
      Returns:
      true if strict parsing succeeds; false otherwise.

      Groovy example:
      // Feb 29, 2025 is invalid because 2025 is not a leap year return dateUtil.isStringValidDateStrict('02/29/2025', 'MM/dd/uuuu')

      Returns:
      false

      SpEL example:
      #isStringValidDateStrict('02/29/2025', 'MM/dd/uuuu')

      Returns:
      false

      Note: Returns false if date is null or does not strictly conform to the given format (including invalid leap-year dates).
    • getStringFromInstant

      public static String getStringFromInstant(Instant instant, String pattern)
      Formats an Instant with the given pattern, rendered in the system default zone and the US locale. A blank pattern falls back to getStringFromInstantPatterned(Instant).
      Parameters:
      instant - the moment to format
      pattern - the output pattern; blank means use the localised short form
      Returns:
      the formatted value, or null if instant is null

      Groovy example:
      return dateUtil.getStringFromInstant(entity.createdDate, "yyyy-MM-dd HH:mm")

      Returns:
      "2026-01-15 09:32"

      SpEL example:
      #getStringFromInstant(#createdDate, 'yyyy-MM-dd HH:mm')

      Returns:
      "2026-01-15 09:32"
    • getStringFromInstantPatterned

      public static String getStringFromInstantPatterned(Instant instant)
      Formats an Instant in the localised SHORT date-time form for the US locale, in the system default zone.

      Despite the name this does not use the application's configured date pattern - it uses the JDK's localised short form, which is why the output looks like 1/15/26, 9:32 AM. Pass an explicit pattern to getStringFromInstant(Instant, String) when the exact shape matters.

      Parameters:
      instant - the moment to format
      Returns:
      the localised short date-time, or null if instant is null

      Groovy example:
      return dateUtil.getStringFromInstantPatterned(entity.createdDate)

      Returns:
      "1/15/26, 9:32 AM"
    • getInstantFromString

      public static Instant getInstantFromString(String instantStr)
      Parses an ISO-8601 string to an Instant. A bare ten-character date is treated as midnight UTC on that day, by appending T00:00:00Z - so "2026-01-15" is an absolute moment, not a local one.
      Parameters:
      instantStr - the value to parse
      Returns:
      the moment, or null if instantStr is null
      Throws:
      DateTimeParseException - if the value is not ISO-8601

      Groovy example:
      return dateUtil.getInstantFromString("2026-01-15")

      Returns:
      2026-01-15T00:00:00Z

      SpEL example:
      #getInstantFromString('2026-01-15T14:30:00Z')

      Returns:
      the parsed instant
    • getLocalStrFromUtcInstant

      public static String getLocalStrFromUtcInstant(Instant utcInstant)
      Renders an Instant in the system default zone as yyyy-MM-dd'T'HH:mm:ss'Z'.

      The trailing Z is a literal, not an offset. The time shown is local to the server, so the output claims UTC while carrying local wall-clock time. Anything that will be parsed downstream should use getIsoDateTimeString(Object) instead, which emits a genuine ISO offset.

      Parameters:
      utcInstant - the moment to render
      Returns:
      the local time with a literal Z suffix, or null if the input is null

      Groovy example:
      return dateUtil.getLocalStrFromUtcInstant(entity.createdDate)

      Returns:
      "2026-01-15T09:32:00Z" - 09:32 server-local, in spite of the Z
    • addDaysObjToDate

      public static LocalDate addDaysObjToDate(LocalDate date, Object daysObj)
      Adds a number of days to a date, taking the count as a Number or numeric String. The untyped variant of addDaysToDate(LocalDate, Integer) - use it where the count comes from a form field or an import row. A count that is neither yields a null count, which returns the date unchanged.
      Parameters:
      date - the starting date
      daysObj - the number of days, positive or negative, as a Number or numeric String
      Returns:
      the shifted date, or the input unchanged if the count could not be read

      Groovy example:
      return dateUtil.addDaysObjToDate(entity.startDate, row.casetivityExtraFields['offset'])

      Returns:
      the start date shifted by the imported offset
    • addDaysToDate

      public static LocalDate addDaysToDate(LocalDate date, Integer days)
      Adds days to a date; a negative count subtracts. Returns the input unchanged when either argument is null - note the difference from addMonthsToDate(LocalDate, Integer) and addYearsToDate(LocalDate, Integer), which return null instead.
      Parameters:
      date - the starting date
      days - the number of days, positive or negative
      Returns:
      the shifted date, or the input unchanged if either argument is null

      Groovy example:
      return dateUtil.addDaysToDate(dateUtil.getLocalDate(entity.startDate), 30)

      Returns:
      thirty days after the start date

      SpEL example:
      #addDaysToDate(#f().date.today(), 14)

      Returns:
      a fortnight from today
    • addMonthsObjToDate

      public static Object addMonthsObjToDate(LocalDate date, Object monthsObj)
      Adds a number of months to a date, taking the count as a Number or numeric String. The untyped variant of addMonthsToDate(LocalDate, Integer).
      Parameters:
      date - the starting date
      monthsObj - the number of months, positive or negative, as a Number or numeric String
      Returns:
      the shifted date as a LocalDate, or null if the count could not be read

      Groovy example:
      return dateUtil.addMonthsObjToDate(entity.startDate, '6')

      Returns:
      six months after the start date
    • addMonthsToDate

      public static Object addMonthsToDate(LocalDate date, Integer months)
      Adds months to a date; a negative count subtracts. Day-of-month is clamped to the target month's length, so 31 January plus one month is 28 or 29 February. Returns null when either argument is null, unlike addDaysToDate(LocalDate, Integer) which returns the input unchanged.
      Parameters:
      date - the starting date
      months - the number of months, positive or negative
      Returns:
      the shifted date as a LocalDate, or null if either argument is null

      Groovy example:
      return dateUtil.addMonthsToDate(dateUtil.getLocalDate(entity.startDate), 6)

      Returns:
      six months after the start date

      SpEL example:
      #addMonthsToDate(#f().date.today(), -3)

      Returns:
      three months ago
    • addYearsObjToDate

      public static Object addYearsObjToDate(LocalDate date, Object yearsObj)
      Adds a number of years to a date, taking the count as a Number or numeric String. The untyped variant of addYearsToDate(LocalDate, Integer).
      Parameters:
      date - the starting date
      yearsObj - the number of years, positive or negative, as a Number or numeric String
      Returns:
      the shifted date as a LocalDate, or null if the count could not be read

      Groovy example:
      return dateUtil.addYearsObjToDate(entity.birthDate, '18')

      Returns:
      the date the person turns eighteen
    • addYearsToDate

      public static Object addYearsToDate(LocalDate date, Integer years)
      Adds years to a date; a negative count subtracts. 29 February in a leap year becomes 28 February in a non-leap target year. Returns null when either argument is null, unlike addDaysToDate(LocalDate, Integer).
      Parameters:
      date - the starting date
      years - the number of years, positive or negative
      Returns:
      the shifted date as a LocalDate, or null if either argument is null

      Groovy example:
      return dateUtil.addYearsToDate(dateUtil.getLocalDate(entity.birthDate), 18)

      Returns:
      the eighteenth birthday

      SpEL example:
      #addYearsToDate(#birthDate, 18)

      Returns:
      the eighteenth birthday
    • daysBetweenObj

      public static Long daysBetweenObj(Object firstDateObj, Object secondDateObj, boolean includeWeekendDays)
      Days from the first date to the second, taking either as any supported date type or format. The untyped variant of getDaysBetween(LocalDate, LocalDate, boolean). Negative when the second date is earlier.
      Parameters:
      firstDateObj - the earlier date, as any supported type
      secondDateObj - the later date, as any supported type
      includeWeekendDays - false to count weekdays only
      Returns:
      the day count, or null if either input is null

      Groovy example:
      return dateUtil.daysBetweenObj(entity.startDate, '2026-03-01', true)

      Returns:
      the number of days to 1 March
    • monthsBetweenObj

      public static Long monthsBetweenObj(Object firstDateObj, Object secondDateObj)
      Whole months from the first date to the second, taking either as any supported date type or format. Negative when the second date is earlier; partial months are truncated.
      Parameters:
      firstDateObj - the earlier date, as any supported type
      secondDateObj - the later date, as any supported type
      Returns:
      the whole-month count, or null if either input is null

      Groovy example:
      return dateUtil.monthsBetweenObj(entity.birthDate, '2026-03-01')

      Returns:
      completed months of age at 1 March
    • yearsBetweenObj

      public static Long yearsBetweenObj(Object firstDateObj, Object secondDateObj)
      Whole years from the first date to the second, taking either as any supported date type or format. This is the usual way to compute an age: partial years are truncated, so it gives completed years.
      Parameters:
      firstDateObj - the earlier date, as any supported type
      secondDateObj - the later date, as any supported type
      Returns:
      the whole-year count, or null if either input is null

      Groovy example:
      return dateUtil.yearsBetweenObj(entity.birthDate, dateUtil.todayDate())

      Returns:
      the age in completed years

      SpEL example:
      #yearsBetweenObj(#birthDate, #f().date.today())

      Returns:
      age in years
    • createDateFromYearMonthDay

      public static LocalDate createDateFromYearMonthDay(Integer year, Integer month, Integer day)
      Builds a LocalDate from its parts. Rejects an impossible date rather than rolling it over, so 31 February throws instead of becoming 2 or 3 March.
      Parameters:
      year - the four-digit year
      month - the month, 1-12
      day - the day of month, 1-31
      Returns:
      the date
      Throws:
      DateTimeException - if the parts do not form a real date
      NullPointerException - if any part is null

      Groovy example:
      return dateUtil.createDateFromYearMonthDay(2026, 1, 15)

      Returns:
      2026-01-15

      SpEL example:
      #createDateFromYearMonthDay(#year, #month, #day)

      Returns:
      the assembled date
    • convertFormatObject

      public static String convertFormatObject(Object dateObj, String fromFormat, String toFormat)
      Restates a date in another format, accepting either a String in fromFormat or an actual date value (in which case fromFormat is ignored).

      A String that does not match fromFormat is returned unchanged rather than rejected, so a mismatched pattern looks like a pass-through. Validate with isStringValidDate(String, String) when that matters.

      Parameters:
      dateObj - the value to restate
      fromFormat - the pattern to parse a String input with
      toFormat - the output pattern
      Returns:
      the reformatted value, the input unchanged if it did not parse, or null if the input is null

      Groovy example:
      return dateUtil.convertFormatObject("01/15/2026", "MM/dd/yyyy", "yyyy-MM-dd")

      Returns:
      "2026-01-15"

      SpEL example:
      #convertFormatObject(#dobString, 'MM/dd/yyyy', 'yyyyMMdd')

      Returns:
      "20260115"
    • convertFormatsObject

      public static String convertFormatsObject(Object dateObj, String[] fromFormats, String toFormat)
      Restates a date in another format, trying several input patterns in order - for imports where a column's format is inconsistent between rows.

      Also understands a "DATE:<epochMillis>" prefix. A String matching none of the patterns is returned unchanged, so a row that failed to parse is indistinguishable from one that was already in the target format. An actual date value ignores fromFormats entirely.

      Parameters:
      dateObj - the value to restate
      fromFormats - patterns to try, in order
      toFormat - the output pattern
      Returns:
      the reformatted value, the input unchanged if nothing matched, or null if the input is null

      Groovy example:
      return dateUtil.convertFormatsObject(row.dob, ["MM/dd/yyyy", "yyyy-MM-dd", "MMddyyyy"] as String[], "yyyy-MM-dd")

      Returns:
      the date normalised, whichever of the three formats the row used
    • convertFormat

      public static String convertFormat(String date, String fromFormat, String toFormat)
      Restates a date String in another format.

      A value that does not match fromFormat is returned unchanged rather than rejected - parsing failures are silent here.

      Parameters:
      date - the value to restate
      fromFormat - the pattern the input is expected to be in
      toFormat - the output pattern
      Returns:
      the reformatted value, or the input unchanged if it did not parse

      Groovy example:
      return dateUtil.convertFormat("01/15/2026", "MM/dd/yyyy", "yyyy-MM-dd")

      Returns:
      "2026-01-15"

      SpEL example:
      #convertFormat(#dobString, 'MM/dd/yyyy', 'yyyy-MM-dd')

      Returns:
      "2026-01-15"
    • isTodayStrPatterned

      @Deprecated public static Boolean isTodayStrPatterned(String dateString)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use isToday(LocalDate) instead.
      Whether a date string is today, parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateString - the value to test
      Returns:
      true if the date is today; true also if the value is blank or does not parse
    • beforeTodayStrPatterned

      @Deprecated public static Boolean beforeTodayStrPatterned(String dateString)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use beforeToday(LocalDate) instead.
      Whether a date string is before today, parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateString - the value to test
      Returns:
      true if the date is before today; true also if the value is blank or does not parse
    • beforeOrEqualsTodayStrPatterned

      @Deprecated public static Boolean beforeOrEqualsTodayStrPatterned(String dateString)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use beforeOrEqualsToday(LocalDate) instead.
      Whether a date string is today or earlier, parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateString - the value to test
      Returns:
      true if the date is today or earlier; true also if the value is blank or does not parse
    • afterTodayStrPatterned

      @Deprecated public static Boolean afterTodayStrPatterned(String dateString)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use afterToday(LocalDate) instead.
      Whether a date string is after today, parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateString - the value to test
      Returns:
      true if the date is after today; true also if the value is blank or does not parse
    • afterOrEqualsTodayStrPatterned

      @Deprecated public static Boolean afterOrEqualsTodayStrPatterned(String dateString)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use afterOrEqualsToday(LocalDate) instead.
      Whether a date string is today or later, parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateString - the value to test
      Returns:
      true if the date is today or later; true also if the value is blank or does not parse
    • compareDate

      public static int compareDate(Instant dateOne, Instant dateTwo)
      Compares two moments, returning a negative number, zero, or a positive number as the first is earlier than, equal to, or later than the second - the shape a sort comparator wants.

      Throws on a null argument, unlike the boolean comparison helpers on this class, which return true.

      Parameters:
      dateOne - the first moment
      dateTwo - the second moment
      Returns:
      negative, zero or positive
      Throws:
      NullPointerException - if either argument is null

      Groovy example:
      return events.sort { a, b -> dateUtil.compareDate(a.occurredAt, b.occurredAt) }

      Returns:
      the events in chronological order
    • isTodayStr

      @Deprecated public static Boolean isTodayStr(String dateString, String pattern)
      Deprecated.
      Parse to a LocalDate with getDateFromString(String, String) and use isToday(LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether a date string is today, parsed with an explicit pattern.
      Parameters:
      dateString - the value to test
      pattern - the pattern to parse with
      Returns:
      true if the date is today; true also if the value is blank or does not parse
    • beforeTodayStr

      @Deprecated public static Boolean beforeTodayStr(String dateString, String pattern)
      Deprecated.
      Parse to a LocalDate with getDateFromString(String, String) and use beforeToday(LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether a date string is before today, parsed with an explicit pattern.
      Parameters:
      dateString - the value to test
      pattern - the pattern to parse with
      Returns:
      true if the date is before today; true also if the value is blank or does not parse
    • beforeOrEqualsTodayStr

      @Deprecated public static Boolean beforeOrEqualsTodayStr(String dateString, String pattern)
      Deprecated.
      Parse to a LocalDate with getDateFromString(String, String) and use beforeOrEqualsToday(LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether a date string is today or earlier, parsed with an explicit pattern.
      Parameters:
      dateString - the value to test
      pattern - the pattern to parse with
      Returns:
      true if the date is today or earlier; true also if the value is blank or does not parse
    • afterTodayStr

      @Deprecated public static Boolean afterTodayStr(String dateString, String pattern)
      Deprecated.
      Parse to a LocalDate with getDateFromString(String, String) and use afterToday(LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether a date string is after today, parsed with an explicit pattern.
      Parameters:
      dateString - the value to test
      pattern - the pattern to parse with
      Returns:
      true if the date is after today; true also if the value is blank or does not parse
    • afterOrEqualsTodayStr

      @Deprecated public static Boolean afterOrEqualsTodayStr(String dateString, String pattern)
      Deprecated.
      Parse to a LocalDate with getDateFromString(String, String) and use afterOrEqualsToday(LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether a date string is today or later, parsed with an explicit pattern.
      Parameters:
      dateString - the value to test
      pattern - the pattern to parse with
      Returns:
      true if the date is today or later; true also if the value is blank or does not parse
    • sameDateStrPatterned

      @Deprecated public static Boolean sameDateStrPatterned(String dateOneStr, String dateTwoStr)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use sameDate(LocalDate, LocalDate) instead.
      Whether the first date string is the same day as the second, both parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      Returns:
      true if the first is the same day as the second; true also if either is blank or does not parse
    • beforeDateStrPatterned

      @Deprecated public static Boolean beforeDateStrPatterned(String dateOneStr, String dateTwoStr)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use beforeDate(LocalDate, LocalDate) instead.
      Whether the first date string is before the second, both parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      Returns:
      true if the first is before the second; true also if either is blank or does not parse
    • beforeOrEqualsDateStrPatterned

      @Deprecated public static Boolean beforeOrEqualsDateStrPatterned(String dateOneStr, String dateTwoStr)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use beforeOrEqualsDate(LocalDate, LocalDate) instead.
      Whether the first date string is on or before the second, both parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      Returns:
      true if the first is on or before the second; true also if either is blank or does not parse
    • afterDateStrPatterned

      @Deprecated public static Boolean afterDateStrPatterned(String dateOneStr, String dateTwoStr)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use afterDate(LocalDate, LocalDate) instead.
      Whether the first date string is after the second, both parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      Returns:
      true if the first is after the second; true also if either is blank or does not parse
    • afterOrEqualsDateStrPatterned

      @Deprecated public static Boolean afterOrEqualsDateStrPatterned(String dateOneStr, String dateTwoStr)
      Deprecated.
      Works on formatted strings using the application-configured date pattern, so its behaviour changes with configuration and a mismatched string compares as equal rather than failing. Parse to a LocalDate with getLocalDate(Object) and use afterOrEqualsDate(LocalDate, LocalDate) instead.
      Whether the first date string is on or after the second, both parsed with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      Returns:
      true if the first is on or after the second; true also if either is blank or does not parse
    • sameDateStr

      public static Boolean sameDateStr(String dateOneStr, String dateTwoStr, String pattern)
      Deprecated.
      Parse to LocalDate values and use sameDate(LocalDate, LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether the first date string is the same day as the second, both parsed with an explicit pattern.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      Returns:
      true if the first is the same day as the second; true also if either is blank or does not parse
    • beforeDateStr

      public static Boolean beforeDateStr(String dateOneStr, String dateTwoStr, String pattern)
      Deprecated.
      Parse to LocalDate values and use beforeDate(LocalDate, LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether the first date string is before the second, both parsed with an explicit pattern.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      Returns:
      true if the first is before the second; true also if either is blank or does not parse
    • beforeOrEqualsDateStr

      public static Boolean beforeOrEqualsDateStr(String dateOneStr, String dateTwoStr, String pattern)
      Deprecated.
      Parse to LocalDate values and use beforeOrEqualsDate(LocalDate, LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether the first date string is on or before the second, both parsed with an explicit pattern.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      Returns:
      true if the first is on or before the second; true also if either is blank or does not parse
    • afterDateStr

      public static Boolean afterDateStr(String dateOneStr, String dateTwoStr, String pattern)
      Deprecated.
      Parse to LocalDate values and use afterDate(LocalDate, LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether the first date string is after the second, both parsed with an explicit pattern.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      Returns:
      true if the first is after the second; true also if either is blank or does not parse
    • afterOrEqualsDateStr

      public static Boolean afterOrEqualsDateStr(String dateOneStr, String dateTwoStr, String pattern)
      Deprecated.
      Parse to LocalDate values and use afterOrEqualsDate(LocalDate, LocalDate) instead, so an unparseable value fails rather than comparing as equal.
      Whether the first date string is on or after the second, both parsed with an explicit pattern.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      Returns:
      true if the first is on or after the second; true also if either is blank or does not parse
    • isToday

      public static Boolean isToday(LocalDate date)
      Whether a date is today - that is, the same calendar day as today.
      Parameters:
      date - the date to test
      Returns:
      true if the date is the same calendar day as today

      Groovy example:
      return dateUtil.isToday(dateUtil.getLocalDate(entity.dueDate))

      Returns:
      true when the due date is the same calendar day as today

      SpEL example:
      #isToday(#dueDate)

      Returns:
      true when the due date is the same calendar day as today

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeToday

      public static Boolean beforeToday(LocalDate date)
      Whether a date is before today - that is, strictly earlier than today.
      Parameters:
      date - the date to test
      Returns:
      true if the date is strictly earlier than today

      Groovy example:
      return dateUtil.beforeToday(dateUtil.getLocalDate(entity.dueDate))

      Returns:
      true when the due date is strictly earlier than today

      SpEL example:
      #beforeToday(#dueDate)

      Returns:
      true when the due date is strictly earlier than today

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeOrEqualsToday

      public static Boolean beforeOrEqualsToday(LocalDate date)
      Whether a date is today or earlier - that is, today or earlier.
      Parameters:
      date - the date to test
      Returns:
      true if the date is today or earlier

      Groovy example:
      return dateUtil.beforeOrEqualsToday(dateUtil.getLocalDate(entity.dueDate))

      Returns:
      true when the due date is today or earlier

      SpEL example:
      #beforeOrEqualsToday(#dueDate)

      Returns:
      true when the due date is today or earlier

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterToday

      public static Boolean afterToday(LocalDate date)
      Whether a date is after today - that is, strictly later than today.
      Parameters:
      date - the date to test
      Returns:
      true if the date is strictly later than today

      Groovy example:
      return dateUtil.afterToday(dateUtil.getLocalDate(entity.dueDate))

      Returns:
      true when the due date is strictly later than today

      SpEL example:
      #afterToday(#dueDate)

      Returns:
      true when the due date is strictly later than today

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterOrEqualsToday

      public static Boolean afterOrEqualsToday(LocalDate date)
      Whether a date is today or later - that is, today or later.
      Parameters:
      date - the date to test
      Returns:
      true if the date is today or later

      Groovy example:
      return dateUtil.afterOrEqualsToday(dateUtil.getLocalDate(entity.dueDate))

      Returns:
      true when the due date is today or later

      SpEL example:
      #afterOrEqualsToday(#dueDate)

      Returns:
      true when the due date is today or later

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • sameDate

      public static Boolean sameDate(LocalDate dateOne, LocalDate dateTwo)
      Whether the first date is the same calendar day as the second.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      Returns:
      true if dateOne is the same calendar day as dateTwo

      Groovy example:
      return dateUtil.sameDate(startDate, endDate)

      Returns:
      true when the first date is the same calendar day as the second

      SpEL example:
      #sameDate(#startDate, #endDate)

      Returns:
      true when the first date is the same calendar day as the second

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeDate

      public static Boolean beforeDate(LocalDate dateOne, LocalDate dateTwo)
      Whether the first date is strictly earlier than the second.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      Returns:
      true if dateOne is strictly earlier than dateTwo

      Groovy example:
      return dateUtil.beforeDate(startDate, endDate)

      Returns:
      true when the first date is strictly earlier than the second

      SpEL example:
      #beforeDate(#startDate, #endDate)

      Returns:
      true when the first date is strictly earlier than the second

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeOrEqualsDate

      public static Boolean beforeOrEqualsDate(LocalDate dateOne, LocalDate dateTwo)
      Whether the first date is the same day as or earlier than the second.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      Returns:
      true if dateOne is the same day as or earlier than dateTwo

      Groovy example:
      return dateUtil.beforeOrEqualsDate(startDate, endDate)

      Returns:
      true when the first date is the same day as or earlier than the second

      SpEL example:
      #beforeOrEqualsDate(#startDate, #endDate)

      Returns:
      true when the first date is the same day as or earlier than the second

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterDate

      public static Boolean afterDate(LocalDate dateOne, LocalDate dateTwo)
      Whether the first date is strictly later than the second.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      Returns:
      true if dateOne is strictly later than dateTwo

      Groovy example:
      return dateUtil.afterDate(startDate, endDate)

      Returns:
      true when the first date is strictly later than the second

      SpEL example:
      #afterDate(#startDate, #endDate)

      Returns:
      true when the first date is strictly later than the second

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterOrEqualsDate

      public static Boolean afterOrEqualsDate(LocalDate dateOne, LocalDate dateTwo)
      Whether the first date is the same day as or later than the second.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      Returns:
      true if dateOne is the same day as or later than dateTwo

      Groovy example:
      return dateUtil.afterOrEqualsDate(startDate, endDate)

      Returns:
      true when the first date is the same day as or later than the second

      SpEL example:
      #afterOrEqualsDate(#startDate, #endDate)

      Returns:
      true when the first date is the same day as or later than the second

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • startOfToday

      public static Instant startOfToday()
      The most recent UTC midnight - today's date at 00:00:00Z. Note this is a UTC day boundary, not a boundary in the application's configured zone, so in a behind-UTC zone it falls during yesterday evening local time.
      Returns:
      today's UTC midnight

      Groovy example:
      return dateUtil.startOfToday()

      Returns:
      2026-01-15T00:00:00Z

      SpEL example:
      #afterInstant(#createdDate, #startOfToday())

      Returns:
      true for records created today, UTC
    • endOfToday

      public static Instant endOfToday()
      The next UTC midnight - tomorrow's date at 00:00:00Z, which is the exclusive upper bound of today. Use it as a half-open range end rather than trying to express "23:59:59".
      Returns:
      tomorrow's UTC midnight

      Groovy example:
      return dateUtil.endOfToday()

      Returns:
      2026-01-16T00:00:00Z

      SpEL example:
      #beforeInstant(#createdDate, #endOfToday())

      Returns:
      true for anything created before tomorrow
    • beforeTodayInst

      public static Boolean beforeTodayInst(Instant date)
      Whether a moment falls before today began, comparing against startOfToday(). The boundaries are UTC midnights, not midnights in the application's configured zone.
      Parameters:
      date - the moment to test
      Returns:
      true if the moment falls before today began

      Groovy example:
      return dateUtil.beforeTodayInst(entity.createdDate)

      Returns:
      true when the record was created before today began

      SpEL example:
      #beforeTodayInst(#createdDate)

      Returns:
      true when created before today began

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeOrEqualsTodayInst

      public static Boolean beforeOrEqualsTodayInst(Instant date)
      Whether a moment falls at any point up to the end of today, comparing against endOfToday(). The boundaries are UTC midnights, not midnights in the application's configured zone.
      Parameters:
      date - the moment to test
      Returns:
      true if the moment falls at any point up to the end of today

      Groovy example:
      return dateUtil.beforeOrEqualsTodayInst(entity.createdDate)

      Returns:
      true when the record was created at any point up to the end of today

      SpEL example:
      #beforeOrEqualsTodayInst(#createdDate)

      Returns:
      true when created at any point up to the end of today

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterTodayInst

      public static Boolean afterTodayInst(Instant date)
      Whether a moment falls after today ended, comparing against endOfToday(). The boundaries are UTC midnights, not midnights in the application's configured zone.
      Parameters:
      date - the moment to test
      Returns:
      true if the moment falls after today ended

      Groovy example:
      return dateUtil.afterTodayInst(entity.createdDate)

      Returns:
      true when the record was created after today ended

      SpEL example:
      #afterTodayInst(#createdDate)

      Returns:
      true when created after today ended

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterOrEqualsTodayInst

      public static Boolean afterOrEqualsTodayInst(Instant date)
      Whether a moment falls at any point from the start of today onwards, comparing against startOfToday(). The boundaries are UTC midnights, not midnights in the application's configured zone.
      Parameters:
      date - the moment to test
      Returns:
      true if the moment falls at any point from the start of today onwards

      Groovy example:
      return dateUtil.afterOrEqualsTodayInst(entity.createdDate)

      Returns:
      true when the record was created at any point from the start of today onwards

      SpEL example:
      #afterOrEqualsTodayInst(#createdDate)

      Returns:
      true when created at any point from the start of today onwards

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • beforeInstant

      public static Boolean beforeInstant(Instant dateOne, Instant dateTwo)
      Whether the first moment is strictly earlier than the second.
      Parameters:
      dateOne - the moment to test
      dateTwo - the moment to compare against
      Returns:
      true if dateOne is earlier than dateTwo

      Groovy example:
      return dateUtil.beforeInstant(entity.createdDate, entity.dueDate)

      Returns:
      true when creation is earlier than the deadline

      SpEL example:
      #beforeInstant(#createdDate, #dueDate)

      Returns:
      true when creation is earlier than the deadline

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • afterInstant

      public static Boolean afterInstant(Instant dateOne, Instant dateTwo)
      Whether the first moment is strictly later than the second.
      Parameters:
      dateOne - the moment to test
      dateTwo - the moment to compare against
      Returns:
      true if dateOne is later than dateTwo

      Groovy example:
      return dateUtil.afterInstant(entity.createdDate, entity.dueDate)

      Returns:
      true when creation is later than the deadline

      SpEL example:
      #afterInstant(#createdDate, #dueDate)

      Returns:
      true when creation is later than the deadline

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • addHours

      public static Instant addHours(Instant date, long hours)
      Adds hours to an Instant; a negative count subtracts. Throws on a null instant.
      Parameters:
      date - the starting moment
      hours - the number of hours, positive or negative
      Returns:
      the shifted moment

      Groovy example:
      return dateUtil.addHours(entity.createdDate, 48)

      Returns:
      two days after creation

      SpEL example:
      #addHours(#createdDate, -1)

      Returns:
      an hour before creation
    • addMinutes

      public static Instant addMinutes(Instant date, long minutes)
      Adds minutes to an Instant; a negative count subtracts. Throws on a null instant.
      Parameters:
      date - the starting moment
      minutes - the number of minutes, positive or negative
      Returns:
      the shifted moment

      Groovy example:
      return dateUtil.addMinutes(entity.submittedDate, 30)

      Returns:
      the half-hour deadline after submission
    • addSeconds

      public static Instant addSeconds(Instant date, long seconds)
      Adds seconds to an Instant; a negative count subtracts. Throws on a null instant.
      Parameters:
      date - the starting moment
      seconds - the number of seconds, positive or negative
      Returns:
      the shifted moment

      Groovy example:
      return dateUtil.addSeconds(dateUtil.instantNow(), 90)

      Returns:
      ninety seconds from now
    • compareLocalDate

      public static Boolean compareLocalDate(LocalDate dateOne, LocalDate dateTwo, String operator)
      Compares two dates with an operator supplied as a String - the general form behind sameDate(LocalDate, LocalDate) and its siblings. Prefer the named methods; reach for this only when the operator itself is configuration.
      Parameters:
      dateOne - the date to test
      dateTwo - the date to compare against
      operator - one of ">", ">=", "==", "<", "<="; blank or unrecognised is treated as equality
      Returns:
      the result of the comparison

      Groovy example:
      return dateUtil.compareLocalDate(startDate, endDate, "invalid input: '<'=")

      Returns:
      true when the start date is not after the end date

      SpEL example:
      #compareLocalDate(#startDate, #endDate, 'invalid input: '<'=')

      Returns:
      true when start is on or before end

      Note: returns true when either argument is null - a null date is not treated as a failed comparison, so guard for null separately when that matters.
    • compareDateStr

      @Deprecated public static Boolean compareDateStr(String dateOneStr, String dateTwoStr, String pattern, String operator)
      Deprecated.
      Compares two date strings with an operator supplied as a String. Returns true when either value is blank, and false when either fails to parse - so a bad value is indistinguishable from a genuine false.
      Parameters:
      dateOneStr - the value to test
      dateTwoStr - the value to compare against
      pattern - the pattern to parse both values with
      operator - one of ">", ">=", "==", "<", "<="
      Returns:
      the comparison result; true if either value is blank, false if either fails to parse
    • addDaysToDateStr

      @Deprecated public static String addDaysToDateStr(String dateStr, Integer days)
      Deprecated.
      Behaviour depends on configuration, and an unparseable input throws. Parse to a LocalDate and use addDaysToDate(LocalDate, Integer) instead.
      Adds days to a date string, parsing and re-formatting with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateStr - the starting date, in the configured pattern
      days - the number to add, positive or negative
      Returns:
      the shifted date in the same pattern
    • addMonthsToDateStr

      @Deprecated public static String addMonthsToDateStr(String dateStr, Integer months)
      Deprecated.
      Behaviour depends on configuration, and an unparseable input throws. Parse to a LocalDate and use addMonthsToDate(LocalDate, Integer) instead.
      Adds months to a date string, parsing and re-formatting with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateStr - the starting date, in the configured pattern
      months - the number to add, positive or negative
      Returns:
      the shifted date in the same pattern
    • addYearsToDateStr

      @Deprecated public static String addYearsToDateStr(String dateStr, Integer years)
      Deprecated.
      Behaviour depends on configuration, and an unparseable input throws. Parse to a LocalDate and use addYearsToDate(LocalDate, Integer) instead.
      Adds years to a date string, parsing and re-formatting with the application's configured date pattern (default MM/dd/yyyy).
      Parameters:
      dateStr - the starting date, in the configured pattern
      years - the number to add, positive or negative
      Returns:
      the shifted date in the same pattern
    • today

      @Deprecated public static String today()
      Deprecated.
      Returns a formatted string whose shape depends on configuration. Use todayDate() for a LocalDate, or #f().date.today().
      Today's date formatted with the application's configured date pattern.
      Returns:
      today's date as a string
    • todayDate

      @Deprecated public static LocalDate todayDate()
      Deprecated.
      Use #f().date.today(), which is the current expression API for dates.
      Today's date in the system default zone.
      Returns:
      today's date
    • now

      @Deprecated public static String now()
      Deprecated.
      Returns a locale-dependent string. Use instantNow() and format explicitly with getStringFromInstant(Instant, String), or getIsoDateTimeString(Object) for anything machine-readable.
      The current moment in the localised US short date-time form.
      Returns:
      the current date and time as a string
    • instantNow

      @Deprecated public static Instant instantNow()
      Deprecated.
      Use #f().instant.now(), which is the current expression API.
      The current moment.
      Returns:
      now
    • daysBetween

      public static Integer daysBetween(LocalDate dateOne, LocalDate dateTwo)
      Days from the first date to the second, counting every day. Negative when the second date is earlier. For working days use weekdaysBetween(LocalDate, LocalDate).
      Parameters:
      dateOne - the earlier date
      dateTwo - the later date
      Returns:
      the day count, or null if either date is null

      Groovy example:
      return dateUtil.daysBetween(dateUtil.getLocalDate(entity.startDate), dateUtil.todayDate())

      Returns:
      days elapsed since the start date

      SpEL example:
      #daysBetween(#startDate, #f().date.today())

      Returns:
      days elapsed
    • weekdaysBetween

      public static Integer weekdaysBetween(LocalDate dateOne, LocalDate dateTwo)
      Days from the first date to the second, excluding Saturdays and Sundays - for turnaround targets expressed in business days. Negative when the second date is earlier. Holidays are not considered.
      Parameters:
      dateOne - the earlier date
      dateTwo - the later date
      Returns:
      the weekday count, or null if either date is null

      Groovy example:
      return dateUtil.weekdaysBetween(dateUtil.getLocalDate(entity.receivedDate), dateUtil.todayDate())

      Returns:
      business days the case has been open

      SpEL example:
      #weekdaysBetween(#receivedDate, #f().date.today()) > 10

      Returns:
      true once the case is more than ten business days old
    • monthsBetween

      public static Long monthsBetween(LocalDate dateOne, LocalDate dateTwo)
      Whole months from the first date to the second; partial months are truncated. Negative when the second date is earlier.
      Parameters:
      dateOne - the earlier date
      dateTwo - the later date
      Returns:
      the whole-month count, or null if either date is null

      Groovy example:
      return dateUtil.monthsBetween(dateUtil.getLocalDate(entity.birthDate), dateUtil.todayDate())

      Returns:
      age in completed months

      SpEL example:
      #monthsBetween(#birthDate, #f().date.today())

      Returns:
      age in months
    • yearsBetween

      public static Long yearsBetween(LocalDate dateOne, LocalDate dateTwo)
      Whole years from the first date to the second; partial years are truncated, so this gives completed years and is the right way to compute an age. Negative when the second date is earlier.
      Parameters:
      dateOne - the earlier date
      dateTwo - the later date
      Returns:
      the whole-year count, or null if either date is null

      Groovy example:
      return dateUtil.yearsBetween(dateUtil.getLocalDate(entity.birthDate), dateUtil.todayDate())

      Returns:
      age in completed years

      SpEL example:
      #yearsBetween(#birthDate, #f().date.today()) >= 18

      Returns:
      true for an adult
    • getDaysBetween

      public static Integer getDaysBetween(LocalDate dateOne, LocalDate dateTwo, boolean includeWeekendDays)
      Days from the first date to the second, optionally skipping weekends. The general form behind daysBetween(LocalDate, LocalDate) and weekdaysBetween(LocalDate, LocalDate). Negative when the second date is earlier; holidays are not considered.
      Parameters:
      dateOne - the earlier date
      dateTwo - the later date
      includeWeekendDays - true to count every day, false to count weekdays only
      Returns:
      the day count, or null if either date is null

      Groovy example:
      return dateUtil.getDaysBetween(startDate, endDate, false)

      Returns:
      the number of weekdays in the span
    • daysBetweenStr

      @Deprecated public static Integer daysBetweenStr(String dateOneStr, String dateTwoStr, boolean includeWeekdays)
      Deprecated.
      Behaviour depends on configuration and the flag is misnamed. Parse to LocalDate values and use getDaysBetween(LocalDate, LocalDate, boolean) instead.
      Days between two date strings parsed with the application's configured date pattern.

      Note the parameter name: includeWeekdays is passed straight through as the includeWeekendDays flag, so true counts every day and false counts weekdays only - the opposite of what the name suggests.

      Parameters:
      dateOneStr - the earlier date, in the configured pattern
      dateTwoStr - the later date, in the configured pattern
      includeWeekdays - true to count every day, false to count weekdays only
      Returns:
      the day count, or null if either value is null
    • getInstantFromDate

      public static Instant getInstantFromDate(Date date)
      Converts a Date to an Instant, preserving the moment exactly.
      Parameters:
      date - the value to convert
      Returns:
      the equivalent instant, or null if date is null

      Groovy example:
      return dateUtil.getInstantFromDate(legacyTimestamp)

      Returns:
      the same moment as an Instant
    • getInstantFromObject

      public static Instant getInstantFromObject(Object object)
      Coerces an Instant, Date, LocalDate or ISO-8601 String to an Instant. A LocalDate becomes start of day in the system default zone; a String is parsed as ISO-8601, with a bare date meaning midnight UTC. An unparseable string yields null rather than an error.
      Parameters:
      object - the value to convert
      Returns:
      the moment, or null if it could not be interpreted

      Groovy example:
      return dateUtil.getInstantFromObject(row.timestamp)

      Returns:
      the moment, whatever type the source used
    • getIsoDateTimeString

      public static String getIsoDateTimeString(Object object)
      Renders any supported date value as a full ISO-8601 date-time with an explicit UTC offset. This is the form to use for anything another system will parse - an HL7 message, a JSON payload, an outbound API call - because the offset is real, unlike getLocalStrFromUtcInstant(Instant).
      Parameters:
      object - the value to render
      Returns:
      the ISO-8601 date-time in UTC, or null if the input could not be interpreted

      Groovy example:
      return dateUtil.getIsoDateTimeString(entity.createdDate)

      Returns:
      "2026-01-15T14:32:00Z"

      SpEL example:
      #getIsoDateTimeString(#createdDate)

      Returns:
      "2026-01-15T14:32:00Z"
    • elapsedBetweenTimes

      public static Long elapsedBetweenTimes(String hhmmss1, String hhmmss2, String units)
      Time elapsed between two times of day, as an absolute value in the requested units. Both times are placed on today's date, so this measures a within-day gap and cannot span midnight. The result is always positive, whichever order the times are given in.
      Parameters:
      hhmmss1 - the first time, as HH:mm:ss
      hhmmss2 - the second time, as HH:mm:ss
      units - one of "seconds", "minutes", "hours"
      Returns:
      the absolute elapsed time, or null if either time is null or units is not one of the three

      Groovy example:
      return dateUtil.elapsedBetweenTimes("09:00:00", "17:30:00", "hours")

      Returns:
      8

      SpEL example:
      #elapsedBetweenTimes(#startTime, #endTime, 'minutes')

      Returns:
      the gap in minutes
    • randomDate

      public static LocalDate randomDate(LocalDate from, LocalDate to)
      A random date in the inclusive range. For generating test and demonstration data - it is not a secure random. Throws on a null bound.
      Parameters:
      from - the earliest date the result may take
      to - the latest date the result may take
      Returns:
      a date somewhere in the range
      Throws:
      NullPointerException - if either bound is null

      Groovy example:
      return dateUtil.randomDate(dateUtil.getLocalDate("2020-01-01"), dateUtil.todayDate())

      Returns:
      a random date since the start of 2020
    • getYearOfDateByWeeks

      public static Integer getYearOfDateByWeeks(LocalDate date)
      The MMWR (morbidity) year a date belongs to, which is not always its calendar year. MMWR weeks run Sunday to Saturday, so a date in early January can belong to the previous MMWR year and one in late December to the next. Pair it with getWeekOfDateByWeeks(LocalDate) - reporting a week without its MMWR year is ambiguous exactly at the year boundary.
      Parameters:
      date - the date to classify
      Returns:
      the MMWR year

      Groovy example:
      return dateUtil.getYearOfDateByWeeks(dateUtil.getLocalDate("2027-01-01"))

      Returns:
      2026, because 1 January 2027 falls in the 2026 MMWR year

      SpEL example:
      #getYearOfDateByWeeks(#onsetDate)

      Returns:
      the MMWR year for the onset date
    • getStartDateOfYearByWeeks

      public static LocalDate getStartDateOfYearByWeeks(int year)
      The first day of MMWR week 1 for a given MMWR year - the Sunday that begins the epidemiological year. Mostly a helper for getWeekOfDateByWeeks(LocalDate); useful directly when bucketing data into MMWR weeks.
      Parameters:
      year - the MMWR year
      Returns:
      the Sunday that starts MMWR week 1 of that year

      Groovy example:
      return dateUtil.getStartDateOfYearByWeeks(2026)

      Returns:
      the Sunday beginning MMWR week 1 of 2026
    • getWeekOfDateByWeeks

      public static Integer getWeekOfDateByWeeks(LocalDate date)
      The MMWR (morbidity) week number a date falls in, from 1. Weeks run Sunday to Saturday, and a year has 52 or 53 of them. Always report it with getYearOfDateByWeeks(LocalDate), since the week number alone is ambiguous across the year boundary.
      Parameters:
      date - the date to classify
      Returns:
      the MMWR week number, starting at 1

      Groovy example:
      return dateUtil.getWeekOfDateByWeeks(dateUtil.getLocalDate(entity.onsetDate))

      Returns:
      3

      SpEL example:
      #getWeekOfDateByWeeks(#onsetDate)

      Returns:
      the MMWR week for the onset date
    • createDateRange

      public static List<LocalDate> createDateRange(Object minValueInput, Object maxValueInput)
      Every date from the first to the second, inclusive of both ends. Takes either bound as any supported date type or format. Returns an empty list - not an error - when either bound is null or the range is inverted, so it is safe to drive from optional fields.

      The list has one entry per day, so a wide range produces a large list.

      Parameters:
      minValueInput - the first date, included in the result
      maxValueInput - the last date, included in the result
      Returns:
      the dates in the range, or an empty list if either bound is null or inverted

      Groovy example:
      return dateUtil.createDateRange(entity.startDate, entity.endDate)

      Returns:
      every day the coverage spans, including both ends

      SpEL example:
      #createDateRange(#startDate, #endDate).size()

      Returns:
      the number of days covered
    • getCurrentSystemTimezoneOffset

      public static Integer getCurrentSystemTimezoneOffset()
      Returns the server's current UTC offset in minutes, accounting for DST at the current moment.
      The sign follows the JavaScript/browser convention: positive values indicate zones behind UTC (e.g., 300 for UTC-5), negative values indicate zones ahead of UTC.
      Equivalent to calling getSystemTimezoneOffset(Object) with Instant.now().
      Returns:
      the server's UTC offset in minutes at the current instant

      Groovy example:
      return dateUtil.getCurrentSystemTimezoneOffset()

      Returns (for UTC-5 / EST):
      300

      SpEL example:
      #getCurrentSystemTimezoneOffset()
    • getSystemTimezoneOffset

      public static Integer getSystemTimezoneOffset(Object dateObj)
      Returns the server's UTC offset in minutes for the timezone configured on the system, evaluated at the point in time represented by dateObj. DST is taken into account — the offset may differ for the same timezone depending on the supplied date.
      The sign follows the JavaScript/browser convention: positive values indicate zones behind UTC (e.g., 300 for UTC-5), negative values indicate zones ahead of UTC.
      Parameters:
      dateObj - the date/time at which to evaluate the offset; accepts Instant, LocalDate, Date, String, or Long (epoch ms) — any type supported by getDate(Object)
      Returns:
      the server's UTC offset in minutes at the given point in time

      Groovy example:
      // Offset during summer (EDT = UTC-4)
      return dateUtil.getSystemTimezoneOffset("2025-07-01T12:00:00Z")

      Returns:
      240

      SpEL example:
      #getSystemTimezoneOffset("2025-07-01T12:00:00Z")
    • getUserTimezoneOffset

      public static Integer getUserTimezoneOffset()
      Returns the UTC offset in minutes sent by the current user's browser, as reported in the X-Timezone-Offset request header (or the configured equivalent). Returns null if there is no active HTTP request or the header is absent/unparseable.
      The sign follows the JavaScript/browser convention: positive values indicate zones behind UTC (e.g., 300 for UTC-5), negative values indicate zones ahead of UTC.
      This value reflects the user's local browser timezone, not the server timezone.
      Returns:
      the user's UTC offset in minutes, or null if unavailable

      Groovy example:
      return dateUtil.getUserTimezoneOffset()

      Returns (for a user in UTC-6 / CST):
      360

      SpEL example:
      #getUserTimezoneOffset()