由于要做一个自动打卡的功能,需要用到判断是否是节假日,如果是节假日则需要跳过打卡,如果不是节假日或者需要补班则需要打卡。网上没有找到好用的方法和jar包,这里分享一下自己使用的代码。

1、新建节假日表

CREATE TABLE `sys_holidays` (
  `date` varchar(10) NOT NULL COMMENT '日期,作为主键,存储具体的法定节假日及补班日期,格式为 "YYYY-MM-DD"',
  `year` varchar(4) NOT NULL COMMENT '年份',
  `holiday_name` varchar(50) NOT NULL COMMENT '节假日名称,用于标识对应的节假日',
  `is_holiday` tinyint(1) NOT NULL COMMENT '是否为法定节假日,使用布尔值(0或1)表示,0表示非节假日,1表示是节假日',
  `is_workday` tinyint(1) NOT NULL COMMENT '是否为补班日期,使用布尔值(0或1)表示,0表示非补班日期,1表示是补班日期',
  `description` varchar(255) DEFAULT NULL COMMENT '描述,可用于提供关于该日期的额外信息',
  PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2、新建对应实体类


import java.io.Serializable;

public class SysHolidays implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 日期
     */
    private String date;

    /**
     * 年份
     */
    private String year;

    /**
     * 节假日名称
     */
    private String holidayName;

    /**
     * 是否节假日
     */
    private int isHoliday;

    /**
     * 是否补班日
     */
    private int isWorkDay;

    /**
     * 描述信息
     */
    private String description;

    public SysHolidays() {
    }

    public SysHolidays(String date, String year, String holidayName, int isHoliday, int isWorkDay, String description) {
        this.date = date;
        this.year = year;
        this.holidayName = holidayName;
        this.isHoliday = isHoliday;
        this.isWorkDay = isWorkDay;
        this.description = description;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getHolidayName() {
        return holidayName;
    }

    public void setHolidayName(String holidayName) {
        this.holidayName = holidayName;
    }

    public int getIsHoliday() {
        return isHoliday;
    }

    public void setIsHoliday(int isHoliday) {
        this.isHoliday = isHoliday;
    }

    public int getIsWorkDay() {
        return isWorkDay;
    }

    public void setIsWorkDay(int isWorkDay) {
        this.isWorkDay = isWorkDay;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

3、新建对应mapper

public interface SysHolidaysMapper
{
    SysHolidays queryByNowDate();

    int insertAll(@Param("holidays") List<SysHolidays> holidays);

    int deleteByYear(@Param("year") String year);
}

4、新建对应mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.job.mapper.SysHolidaysMapper">

    <resultMap type="com.ruoyi.job.domain.SysHolidays" id="SysHolidaysResult">
        <id property="date" column="date"/>
        <result property="year" column="year"/>
        <result property="holidayName" column="holiday_name"/>
        <result property="isHoliday" column="is_holiday"/>
        <result property="isWorkDay" column="is_workday"/>
        <result property="description" column="description"/>
    </resultMap>

    <insert id="insertAll">
        INSERT INTO `sys_holidays` (`date`, `year`, `holiday_name`, `is_holiday`, `is_workday`, `description`)
        VALUES
        <foreach collection="holidays" item="item" separator=",">
            (#{item.date}, #{item.year}, #{item.holidayName}, #{item.isHoliday}, #{item.isWorkDay}, #{item.description})
        </foreach>
    </insert>


    <delete id="deleteByYear">
        DELETE from sys_holidays where YEAR = #{year}
    </delete>
    <select id="queryByNowDate" resultMap="SysHolidaysResult">
        SELECT date, year, holiday_name, is_holiday, is_workday, description
        from sys_holidays
        where date = CURDATE()
    </select>


</mapper> 

5、新增节假日service

public interface ISysHolidaysService
{
    SysHolidays queryByNowDate();

    int insertAll(List<SysHolidays> holidays);

    int deleteByYear(String year);

    String saveHolidays(String year);

    Boolean isHoliday();
}

6、新增节假日service实现


@Service
public class ISysHolidaysServiceImpl implements ISysHolidaysService {

    @Autowired
    private SysHolidaysMapper sysHolidaysMapper;

    @Override
    public SysHolidays queryByNowDate() {
        return sysHolidaysMapper.queryByNowDate();
    }

    @Override
    public int insertAll(List<SysHolidays> holidays) {
        return sysHolidaysMapper.insertAll(holidays);
    }

    @Override
    public int deleteByYear(String year) {
        return sysHolidaysMapper.deleteByYear(year);
    }

    @Transactional
    @Override
    public String saveHolidays(String year) {
        List<SysHolidays> sysHolidayList = getSysHolidays(year);

        if (!sysHolidayList.isEmpty()) {
            try {
                int deleteRow = deleteByYear(year);
                int insertRow = insertAll(sysHolidayList);
                return String.format("更新节假日数据成功,本次共删除数据:%d行,新增数据:%d行", deleteRow, insertRow);
            } catch (Exception e) {
                throw new RuntimeException("更新节假日数据失败", e);
            }
        }

        return "本次操作未更新数据";
    }

    @Override
    public Boolean isHoliday() {
        // 判断是否是节假日或者补班
        SysHolidays sysHolidays = queryByNowDate();
        if (sysHolidays != null ) {
            if (sysHolidays.getIsHoliday() == 1) {
                return true;
            }
            if (sysHolidays.getIsWorkDay() == 1) {
                return false;
            }
        }

        // 不是节假日,则判断是否为周末,不是周末即为工作日
        LocalDate now = LocalDate.now();
        DayOfWeek dayOfWeek = now.getDayOfWeek();
        return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
    }

    private List<SysHolidays> getSysHolidays(String year) {
        WebClient build = WebClient.builder().baseUrl("https://timor.tech/api/holiday/year/").build();
        Mono<String> responseMono = build.get()
                .uri(year)
                .retrieve()
                .bodyToMono(String.class);

        String block = responseMono.block();
        JSONObject parse = JSONObject.parse(block);
        JSONObject holiday = parse.getJSONObject("holiday");

        return holiday.keySet().stream()
                .map(key -> {
                    JSONObject jsonObject = holiday.getJSONObject(key);
                    String date = jsonObject.getString("date");
                    String name = jsonObject.getString("name");
                    boolean isHoliday = jsonObject.getBoolean("holiday");
                    return new SysHolidays(date, year, name, isHoliday ? 1 : 0, isHoliday ? 0 : 1, name);
                })
                .collect(Collectors.toList());
    }
}

7、新增controller接口用于更新每年节假日数据

每年11月份-12月份左右国务院会发布明年的法定节假日及补班日,我们需要调用第三方接口存入到我们的数据库中以便明年使用。如果第三方接口无法使用可自行根据国务院发布的文档自行编写insert语句插入数据到表格中,不使用接口的方式更新。

@RestController
@RequestMapping("/holiday")
public class HolidayController extends BaseController {

    @Autowired
    private ISysHolidaysService iSysHolidaysService;

    @GetMapping("/save/{year}")
    public String saveHolidays(@PathVariable String year) {
        return iSysHolidaysService.saveHolidays(year);
    }
}