All Downloads are FREE. Search and download functionalities are using the official Maven repository.

yakworks.commons.lang.LocalDateUtils.groovy Maven / Gradle / Ivy

/*
* Copyright 2019 original authors
* SPDX-License-Identifier: Apache-2.0
*/
package yakworks.commons.lang

import java.time.DayOfWeek
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Period
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.time.temporal.ChronoUnit
import java.time.temporal.Temporal
import java.time.temporal.TemporalAdjusters
import java.util.regex.Pattern

import groovy.transform.CompileStatic

/**
 * custom manipulations with dates.
 * (e.g. to get a number of days between dates or to get last day of month, etc)
 */
@CompileStatic
@SuppressWarnings(['MethodCount', 'ReturnNullFromCatchBlock'])
class LocalDateUtils {
    static final Pattern LOCAL_DATE = ~/\d{4}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[01])$/
    static final Pattern ISO_YEAR_MONTH = ~/\d{4}-(0[1-9]|1[0-2])$/
    //custom format for ISO_MONTH with no hyphen
    static final Pattern ISO_YEAR_MONTH_NO_HYPHEN = ~/\d{4}(0[1-9]|1[0-2])$/

    /**
     * - trims first and returns null if empty
     * - try LocalDate.parse and if error then try parsing with DateTimeFormatter.ISO_DATE_TIME
     */
    static LocalDate parse(String date) {
        date = date?.trim()
        if (!date) return null

        try {
            return LocalDate.parse(date)
        } catch (DateTimeParseException e) {
            //try with full dateTime
            return LocalDate.parse(date, DateTimeFormatter.ISO_DATE_TIME)
        }
    }

    static LocalDateTime parseLocalDateTime(String date) {
        date = date?.trim()
        if (!date) return null

        if (date.matches(LOCAL_DATE)) {
            date = "${date}T00:00"
        }
        LocalDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME)
    }

    /**
     * Parse either LocalDateTime or LocalDate depending on format it picks up
     */
    static Temporal parseTemporal(String date) {
        date = date?.trim()
        if (!date) return null

        if (isLocalDate(date)) {
            return parse(date)
        } else {
            try {
                return LocalDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME)
            } catch (DateTimeParseException e) {
                return null
            }
        }
    }

    static boolean isLocalDate(String date){
        date = date?.trim()
        if (!date || !date.matches(LOCAL_DATE)) return false
    }

    static boolean isLocalDateTime(String date){
        date = date?.trim()

        if (!date) return false
        try {
            LocalDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME)
            return true
        } catch (DateTimeParseException e) {
            return false
        }
    }
    /**
     * Returns the first day of the current month and sets time to midnight.
     */
    static LocalDate getFirstDateOfMonth() {
        return getFirstDateOfMonth(LocalDate.now())
    }

    static LocalDate getFirstDateOfMonth(LocalDate locDate) {
        return locDate.with(TemporalAdjusters.firstDayOfMonth());
    }

    static LocalDate getLastDateOfMonth() {
        return getLastDateOfMonth(LocalDate.now())
    }

    static LocalDate getLastDateOfMonth(LocalDate locDate) {
        return locDate.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * Returns the last day of the current week and sets time to before midnight (23:59:59).
     */
    static LocalDate getLastDayOfWeek() {
        getLastDayOfWeek(LocalDate.now())
    }

    static LocalDate getLastDayOfWeek(LocalDate locDate) {
        locDate.with(DayOfWeek.SUNDAY)
    }

    /**
     * Uses Period.between to get the days.
     * If start date is less than end it will be a positive number
     * If start date > end date, number will be negative
     *
     * @param start the start date
     * @param end the end date
     * @return the days dif,
     */
    static int getDaysBetween(LocalDate start, LocalDate end) {
        return Period.between(start, end).days
    }

    /**
     * Get Month difference between two dates, not by caclualting days but using the month number and subtraction
     *
     * Returns int
     * one.month = two.month : 0
     * one.month = (two.month - 1) : 1
     * one.month = (two.month + 1) : -1
     */
    static int getMonthDiff(LocalDate start, LocalDate end) {
        return Period.between(getFirstDateOfMonth(start), getFirstDateOfMonth(end)).months
        // return end.getMonthValue() - start.getMonthValue()
    }

    /**
     * Checks if the current day number is equal to specified day number in a given period.
     *
     * @period ChronoUnit DAYS WEEKS or MONTHS
     * @dayNumber 1-30 for monthly, 1-7 for weekly (1 is Sunday)
     * @return is today the date for a specified period and dayInPeriod
     */
    static boolean isTodayTheDate(ChronoUnit period, int dayNumber) {
        LocalDate thedate = LocalDate.now()
        switch (period) {
            case ChronoUnit.DAYS:
                return true
            case ChronoUnit.WEEKS:
                return DayOfWeek.from(thedate).value == dayNumber
            case ChronoUnit.MONTHS:
                return thedate.getDayOfMonth() == dayNumber
            default:
                return false
        }
    }

    static boolean isSameDay(LocalDateTime date1, LocalDateTime date2){
        return date1.toLocalDate() == date2.toLocalDate()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy