java处理时间-去除节假日以及双休日


有些场景需要计算数据非工作日的情况,eg:统计每个人每月工作日签到情况等,就需要去除法定节假日和工作日,可以新建一个表用来存储和维护这些非工作日。

一、建表:activity_holiday_info

CREATE TABLE `activity_holiday_info` (
  `holiday_id` int NOT NULL AUTO_INCREMENT,
  `holiday_name` varchar(20) DEFAULT NULL COMMENT '节假日名称',
  `holiday_time` date DEFAULT NULL COMMENT '节假日时间',
  `remark` varchar(50) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`holiday_id`)
) ENGINE=InnoDB  COMMENT='节假日';

二、java代码

  • 可以先按照年月初始化周末数据入库 initHolidays();
  • 按照年份查询已录入系统的非工作日给前端,标记在日历📅中回显展示,供运营人员查看和修改 queryHolidays()。
  • 特殊节假日带官方发布该年份后,人工从前端日历控件去修改维护 mergeHolidays()。

1、ActivitityHolidayController.java

/**
 * @author qy
 * 非工作日维护
 */
@RestController
@RequestMapping("/holidays")
@Slf4j
@Api(tags = "非工作日维护")
public class ActivitityHolidayController {

    @Autowired
    private ActivityHolidayInfoService activityHolidayInfoService;

    /**
     * 非工作日维护,周六周日按年份需初始化,特殊、节假日页面维护
     */
    @ApiOperation(value = "按年份初始化周末")
    @GetMapping(value = "/{year}/initDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", dataType = "String", paramType = "path")
    })
    public Result<Boolean> initHolidays(@PathVariable String year) {
        activityHolidayInfoService.initHolidays(year);
        return Result.success(Boolean.TRUE);
    }


    /**
     * 查询已录入系统的非工作日给前端,标记在日历📅中展示。
     */
    @ApiOperation(value = "查询已录入系统的非工作日")
    @GetMapping(value = "/{year}/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", dataType = "String", paramType = "path")
    })
    public Result<List<ActivityHolidayInfo>> queryHolidays(@PathVariable String year) {
        return Result.success(activityHolidayInfoService.queryHolidays(year));
    }

    /**
     * 更新该年份的非工作日()
     */
    @ApiOperation(value = "更新该年份的非工作日")
    @PutMapping(value = "/{year}/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", dataType = "String", paramType = "path")
    })
    public Result<Boolean> mergeHolidays(@RequestBody List<ActivityHolidayInfo> holidayInfos, @PathVariable String year) {
        activityHolidayInfoService.mergeHolidays(holidayInfos, year);
        return Result.success(Boolean.TRUE);
    }
}

2、ActivityHolidayInfoService.java

public interface ActivityHolidayInfoService extends IService<ActivityHolidayInfo> {

    /**
     * 初始化当年周六、周末
     */
    void initHolidays(String year);

    /**
     * 查询已录入系统的非工作日
     */
    List<ActivityHolidayInfo> queryHolidays(String year);

    /**
     * 更新该年份的非工作日
     */
    void mergeHolidays(List<ActivityHolidayInfo> holidayInfos, String year);
}

3、ActivityHolidayInfoServiceImpl.java


@Service
public class ActivityHolidayInfoServiceImpl extends ServiceImpl<ActivityHolidayInfoMapper, ActivityHolidayInfo> implements ActivityHolidayInfoService {

    /**
     * 查询改年份已录入系统的非工作日
     */
    @Override
    public List<ActivityHolidayInfo> queryHolidays(String year) {
        QueryWrapper<ActivityHolidayInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().likeRight(ActivityHolidayInfo::getHolidayTime, year);
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 更新该年份的非工作日
     */
    @Override
    public void mergeHolidays(List<ActivityHolidayInfo> holidayInfos, String year) {
        remove(new QueryWrapper<ActivityHolidayInfo>()
                .lambda()
                .likeRight(ActivityHolidayInfo::getHolidayTime, year));
        saveBatch(holidayInfos);
    }

    // 根据年份和月份获取当月的所有日期
    public static List<String> getDayByMonth(int month, String year) {
        List<String> data = new ArrayList<>();
        try {
            Calendar c = Calendar.getInstance();
            // 获取当前的年份
            // int year = c.get(Calendar.YEAR);
            // 获取本月的总天数
            int dayCount = c.getActualMaximum(Calendar.DAY_OF_MONTH);
            // 定义时间格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            // 开始日期为当前年月拼接1号
            Date startDate = sdf.parse(year + "-" + month + "-01");
            // 结束日期为当前年月拼接该月最大天数
            Date endDate = sdf.parse(year + "-" + month + "-" + dayCount);
            // 设置calendar的开始日期
            c.setTime(startDate);
            // 当前时间小于等于设定的结束时间
            while (c.getTime().compareTo(endDate) <= 0) {
                String time = sdf.format(c.getTime());
                data.add(time);
                // 当前日期加1
                c.add(Calendar.DATE, 1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * 初始化当年周六、周末
     */
    @Override
    public   void initHolidays(String year) {
        try {
            // 拿到当年中的所有日期
            List<String> dateList = new ArrayList<>();
            for (int i = 1; i <= 12; i++) {
                dateList.addAll(getDayByMonth(i, year));
            }
            dateList = dateList.stream().distinct().collect(Collectors.toList());
            // set 日期
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            List<ActivityHolidayInfo> activityHolidayInfo = new ArrayList<>();
            // 添加当年所有日期数据
            for (String date : dateList) {
                ActivityHolidayInfo serviceDate = new ActivityHolidayInfo();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(simpleDateFormat.parse(date));
                // index 值为 7 时 是周六  值为 1 时是末, 美国周六是一周的最后一天,周日是一周的最后一天
                int index = calendar.get(Calendar.DAY_OF_WEEK);
                if (index == 7) {
                    serviceDate.setHolidayName("周六");
                    serviceDate.setRemark("周末");
                    serviceDate.setHolidayTime(simpleDateFormat.parse(date));
                    activityHolidayInfo.add(serviceDate);
                } else if (index == 1) {
                    serviceDate.setHolidayName("周日");
                    serviceDate.setRemark("周末");
                    serviceDate.setHolidayTime(simpleDateFormat.parse(date));
                    activityHolidayInfo.add(serviceDate);
                }
            }
           if (!CollectionUtils.isEmpty(activityHolidayInfo)) {
               //先删除该年份数据
                remove(new QueryWrapper<ActivityHolidayInfo>()
                        .lambda()
                        .likeRight(ActivityHolidayInfo::getHolidayTime, year));
               //再批量插入
                saveBatch(activityHolidayInfo);
            }
        } catch (Exception e) {
            log.error("日期初始化错误");
            e.printStackTrace();
        }
    }
}

三、测试效果

postman请求:http://x.x.x.x:8080/holidays/年份/initDate

数据库情况:

在这里插入图片描述

要判断当前日期是否是节假日双休日,可以使用Java 8中的java.time包中的类和方法。具体可以按照以下步骤进行操作: 1. 首先,需要创建一个LocalDate对象表示当前日期,可以使用now()方法获取当前日期: ```java LocalDate today = LocalDate.now(); ``` 2. 判断当前日期是否是节假日,可以使用第三方API或者自己实现一个判断方法。这里以自己实现为例,假设节假日包括元旦节、春节、清明节、劳动节、端午节、中秋节、国庆节。可以定义一个方法,判断当前日期是否在这些节假日之一: ```java public static boolean isHoliday(LocalDate date) { int month = date.getMonthValue(); int day = date.getDayOfMonth(); if ((month == 1 && day == 1) || // 元旦节 (month == 2 && day >= 4 && day <= 10) || // 春节 (month == 4 && day >= 4 && day <= 6) || // 清明节 (month == 5 && day >= 1 && day <= 3) || // 劳动节 (month == 6 && day >= 12 && day <= 14) || // 端午节 (month == 9 && day >= 19 && day <= 21) || // 中秋节 (month == 10 && day >= 1 && day <= 7)) { // 国庆节 return true; } return false; } ``` 3. 判断当前日期是否是双休日,可以使用DayOfWeek枚举类的值来判断。如果当前日期是星期六或星期日,则认为是双休日。可以使用getDayOfWeek()方法获取当前日期的星期几: ```java public static boolean isWeekend(LocalDate date) { DayOfWeek dayOfWeek = date.getDayOfWeek(); return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY; } ``` 4. 最后,可以通过调用上面定义的方法来判断当前日期是否是节假日双休日: ```java if (isHoliday(today)) { System.out.println("今天是节假日!"); } else if (isWeekend(today)) { System.out.println("今天是双休日!"); } else { System.out.println("今天是工作日!"); } ``` 需要注意的是,判断节假日需要根据具体情况调整,例如春节日期会根据农历而有所不同。同时,如果需要判断其他国家或地区的节假日,也需要根据当地情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只IT攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值