[Java] Holiday judgment sample

Overview

I wanted to run batch only on weekdays, so I could easily exclude Saturdays and Sundays with cron, but I couldn't exclude holidays quickly, so Java decided that it was a holiday. It feels like I searched a little. I couldn't find many Java samples, so I will publish it.

Caution

――The transfer holiday is a little complicated so I will not consider it --Does not consider past years --This year (2020) is special, so we will not consider it. --The formula for Vernal Equinox Day and Autumnal Equinox Day is valid only from 1980 to 2099.

environment

1. Create a holiday definition class

--Fixed date, Happy Monday, Vernal Equinox Day, Autumnal Equinox Day 4 patterns

PublicHoliday.java


package com.tamorieeeen.sample.consts;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 *public holiday
 *
 * @author tamorieeeen
 *
 */
@Getter
@AllArgsConstructor
public enum PublicHoliday {

    NEWYEAR("New Year's Day", "fixed", 1, 1, 0),
    ADULT("Coming of age day", "monday", 1, 0, 2),
    FOUNDATION("Foundation Day", "fixed", 2, 11, 0),
    BIRTHDAY("The emperor's birthday", "fixed", 2, 23, 0),
    SPRING("Vernal Equinox Day", "spring", 3, 0, 0),
    SHOWA("Showa Day", "fixed", 4, 29, 0),
    CONSTITUTION("Constitution Memorial Day", "fixed", 5, 3, 0),
    GREEN("Greenery day", "fixed", 5, 4, 0),
    CHILDREN("Children's day", "fixed", 5, 5, 0),
    SEA("Marine day", "monday", 7, 0, 3),
    MOUNTAIN("Mountain day", "fixed", 8, 11, 0),
    AGED("Respect for the aged day", "monday", 9, 0, 3),
    AUTUMN("Autumnal Equinox Day", "autumn", 9, 0, 0),
    SPORTS("Sports day", "monday", 10, 0, 2),
    CULTURE("Culture Day", "fixed", 11, 3, 0),
    THANKSGIVING("Labor Thanksgiving Day", "fixed", 11, 23, 0);

    private String name;
    // fixed:Fixed date
    // monday:Monday
    // spring:Vernal Equinox Day
    // autumn:Autumnal Equinox Day
    private String type;
    //Month
    private int month;
    //Date type:Day
    private int dayOfMonth;
    //Monday type:Something
    private int weekOfMonth;

    /**
     *Get fixed holidays
     */
    public static List<PublicHoliday> getFixedHoliday() {

        return Stream.of(values())
                .filter(v -> v.type.equals("fixed"))
                .collect(Collectors.toList());
    }

    /**
     *Get happy monday
     */
    public static List<PublicHoliday> getHappyMonday() {

        return Stream.of(values())
                .filter(v -> v.type.equals("monday"))
                .collect(Collectors.toList());
    }

    /**
     *Get Vernal Equinox Day
     */
    public static PublicHoliday getSpringDay() {

        return Stream.of(values())
                .filter(v -> v.type.equals("spring"))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException());
    }

    /**
     *Get Autumnal Equinox Day
     */
    public static PublicHoliday getAutumnDay() {

        return Stream.of(values())
                .filter(v -> v.type.equals("autumn"))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException());
    }
}

2. Create a holiday judgment class

--Use Calendar.DAY_OF_WEEK_IN_MONTH on what Monday --Vernal Equinox Day: ʻint (20.8431 + 0.242194 * (year-1980)-int ((year-1980) / 4)) --Autumn Equinox Day: ʻint (23.2488 + 0.242194 * (year-1980)-int ((year-1980) / 4))

HolidayService.java


package com.tamorieeeen.sample.service;

import java.time.LocalDate;
import java.util.Calendar;
import org.springframework.stereotype.Service;

import com.tamorieeeen.sample.consts.PublicHoliday;

/**
 *
 * @author tamorieeeen
 *
 */
@Service
public class HolidayService {

    //365 for a year.242194 days, so 0 per year.242 194 days ahead
    private static final double DIFF_OF_YEAR = 0.242194;
    //Calculated from 1980, which was a leap year
    private static final int LEAP_YEAR = 1980;
    //Equinox time of 1980 "20.8431 days "
    private static final double SPRING_DAY_BASE = 20.8431;
    //Time of the autumn equinox of 1980 "23.2488 days "
    private static final double AUTMN_DAY_BASE = 23.2488;

    /**
     *Whether it is a holiday
     */
    public boolean isHoliday() {

        LocalDate today = LocalDate.now();

        if (this.isFixedHoliday(today) || this.isHappyMonday(today) ||
                this.isSpringDay(today) || this.isAutmnDay(today)) {

            return true;
        }

        return false;
    }

    /**
     *Whether it is a fixed holiday
     */
    private boolean isFixedHoliday(LocalDate today) {

        return PublicHoliday.getFixedHoliday()
                .stream()
                .map(h -> LocalDate.of(
                        today.getYear(), h.getMonth(), h.getDayOfMonth()))
                .anyMatch(h -> h.isEqual(today));
    }

    /**
     *Whether it's happy monday
     */
    private boolean isHappyMonday(LocalDate today) {

        return PublicHoliday.getHappyMonday()
                .stream()
                .map(h -> LocalDate.of(
                        today.getYear(), h.getMonth(),
                        this.getDayOfMonth(h.getMonth(), h.getWeekOfMonth())))
                .anyMatch(h -> h.isEqual(today));
    }

    /**
     *Get Happy Monday Date
     */
    private int getDayOfMonth(int month, int weekOfMonth) {

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_WEEK, 2);
        cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, weekOfMonth);

        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     *Vernal Equinox Day
     */
    private boolean isSpringDay(LocalDate today) {

        int dayOfMonth =
                this.getMovedDays(today.getYear(), SPRING_DAY_BASE)
                - this.getLeapYearDays(today.getYear());
        LocalDate springDay = LocalDate.of(
                today.getYear(),
                PublicHoliday.getSpringDay().getMonth(),
                dayOfMonth);

        return today.isEqual(springDay);
    }

    /**
     *Whether it's Autumnal Equinox Day
     */
    private boolean isAutmnDay(LocalDate today) {

        int dayOfMonth =
                this.getMovedDays(today.getYear(), AUTMN_DAY_BASE)
                - this.getLeapYearDays(today.getYear());
        LocalDate autmnDay = LocalDate.of(
                today.getYear(),
                PublicHoliday.getAutumnDay().getMonth(),
                dayOfMonth);

        return today.isEqual(autmnDay);
    }

    /**
     *Get what's going on
     */
    private int getMovedDays(int year, double baseDay) {

        return (int) Math.floor(baseDay + this.getDiffDays(year));
    }

    /**
     *Get the difference from 1980
     */
    private double getDiffDays(int year) {

        return DIFF_OF_YEAR * (year - LEAP_YEAR);
    }

    /**
     *Get a leap year
     */
    private int getLeapYearDays(int year) {

        return (int) Math.floor((year - LEAP_YEAR) / 4.0);
    }
}

3. Create a call class

--If holidayService.isHoliday () is true, it is a holiday, if it is false, it is a weekday.

SampleController.java


package com.tamorieeeen.sample.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.tamorieeeen.sample.service.HolidayService;

import lombok.extern.slf4j.Slf4j;

/**
 *
 * @author tamorieeeen
 *
 */
@Slf4j
@Controller
public class SampleController {

    @Autowired
    private HolidayService holidayService;

    @GetMapping("/sample")
    public String top() {

        if (holidayService.isHoliday()) {
            log.info("today is holiday.");
        } else {
            log.info("today is weekday.");
        }

        return "sample";
    }
}

Impressions

Calculation of vernal and autumnal equinox days is troublesome!

reference

About the Cabinet Office "National Holidays" Find the date of "the third Monday of this month" Calculate Vernal Equinox Day and Autumnal Equinox Day with PHP

Recommended Posts

[Java] Holiday judgment sample
[Java] Generics sample
Java sample code 02
Java sample code 03
Selenium sample (Java)
Java GUI sample
Java sample code 04
Java sample code 01
[Java] logback slf4j sample
Java parallelization code sample collection
Java standard log output sample
[Java] Multiple OR condition judgment
Selenium Sample Reservation Form (Java)
Java Unit Test Library-Artery-Current Date Judgment
Java 9 new features and sample code
A simple sample callback in Java
Java
[Java] Judgment of identity and equivalence
BloomFilter description and implementation sample (JAVA)
[Java] Date period duplication check sample
EXCEL file update sample with JAVA
Java
Sample vending machine made in Java
Sample code using Minio from Java
Java Unit Test Library-Artery / JUnit4-Numerical equality judgment
Sample code collection for Azure Java development
[Java] Spam judgment using morphological analysis "lucene-gosen"
Sample vending machine made in Java (classification)
[Java] Character judgment / character string formatting (AOJ11 --character count)
Sample to unzip gz file in Java