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.
――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.
--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());
}
}
--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);
}
}
--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";
}
}
Calculation of vernal and autumnal equinox days is troublesome!
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