Java 万年历、周六日计算、节假日导出

目录

(1)通过 Java 的基本语法来实现万年历

(2)Java 获取一年中所有的周六和周日

(3)Java 节假日导入导出


(1)通过 Java 的基本语法来实现万年历

        在 Java 的时间计算方面还有很多好用的工具类,Java 常用的工具类封装框架链接如下:HUTool 框架官网

package com.taier.pulsar.date_utils;

import java.util.Scanner;

/**
 * @author swadian2008
 */
public class DateUtils {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入年:");
        int year = sc.nextInt();
        System.out.println("请输入月份:");
        int month = sc.nextInt();
        //1.计算1900.1.1到输入年的天数
        int dayOfYear = 0;
        for (int i = 1900; i < year; i++) {
            if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) { // 闰年
                dayOfYear += 366;
            } else {
                dayOfYear += 365;
            }
        }
        //2.计算1月到输入月的天数
        int dayOfMonth = 0;
        for (int i = 1; i < month; i++) {
            switch (i) {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    dayOfMonth += 31;
                    break;
                case 4:
                case 6:
                case 9:
                case 11:
                    dayOfMonth += 30;
                    break;
                case 2:
                    if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) {
                        dayOfMonth += 29;
                    } else {
                        dayOfMonth += 28;
                    }
                    break;
            }
        }
        //3.获取输入月的天数
        int day = 0;
        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                day = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                day = 30;
                break;
            case 2:
                if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) {
                    day = 29;
                } else {
                    day = 28;
                }
                break;
        }
        //4.计算星期
        int allDay = dayOfYear + dayOfMonth + 1;
        int week = allDay % 7; // 计算余数在星期中的位置
        int count = 0;// 计数器,记录日期的空格

        System.out.println("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六");
        //5.打印空格
        for (int i = 1; i <= week; i++) {
            System.out.print("\t\t\t");
            count++;
        }
        //6. 打印日历
        for (int i = 1; i <= day; i++) {
            if (i < 10) { // 为了格式化
                System.out.print(i + "\t\t\t");
            } else {
                System.out.print(i + "\t\t");
            }
            count++;
            //若记录数是七的倍数,换行输出
            if (count % 7 == 0) {
                System.out.println();
            }
        }
    }
}

        打印效果如下:

(2)Java 获取一年中所有的周六和周日

        下边的示例中使用了一个Map来收集周六和周日,可以根据需要进行调节:

import static java.time.temporal.TemporalAdjusters.firstInMonth;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

/**
 * @author swadian2008
 */
public class WeekDay {

    public static void main(String[] args) {
        // 创建代表一年中第一天的LocalDate对象。
        int year = 2023;
        LocalDate now = LocalDate.of(year, Month.JANUARY, 1);
        Map<String, List<Integer>> weekMap = new HashMap<>(12);
        // 第一个星期六
        LocalDate saturday = now.with(firstInMonth(DayOfWeek.SATURDAY));
        do {
            String satMonth = String.valueOf(saturday.getMonthValue());
            if (CollectionUtils.isEmpty(weekMap.get(satMonth))) {
                weekMap.put(satMonth, new ArrayList<>(Arrays.asList(saturday.getDayOfMonth())));
            } else {
                List<Integer> values = weekMap.get(satMonth);
                values.add(saturday.getDayOfMonth());
                Collections.sort(values);
                weekMap.put(satMonth, values);
            }
            // 迭代一个星期
            saturday = saturday.plus(Period.ofDays(7));
        } while (saturday.getYear() == year);
        // 第一个星期天
        LocalDate sunday = now.with(firstInMonth(DayOfWeek.SUNDAY));
        do {
            String sunMonth = String.valueOf(sunday.getMonthValue());
            if (CollectionUtils.isEmpty(weekMap.get(sunMonth))) {
                weekMap.put(sunMonth, new ArrayList<>(Arrays.asList(sunday.getDayOfMonth())));
            } else {
                List<Integer> values = weekMap.get(sunMonth);
                values.add(sunday.getDayOfMonth());
                Collections.sort(values);
                weekMap.put(sunMonth, values);
            }
            // 迭代一个星期
            sunday = sunday.plus(Period.ofDays(7));
        } while (sunday.getYear() == year);

        Map<String, List<Integer>> sortWeekMap = weekMap.entrySet().stream().sorted((e1, e2) ->
            Integer.compare(Integer.parseInt(e1.getKey()), Integer.parseInt(e2.getKey())))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1,
                LinkedHashMap::new));
        for (Entry<String, List<Integer>> map : sortWeekMap.entrySet()) {
            System.out.println(map.getKey() + "月:" + map.getValue().toString());
        }
    }
}

        打印效果如下:

(3)Java 节假日导入导出

        Java 节假日导入导出会要操作一些 excel 文件,推荐使用 Easy Excel

        使用该框架后,就不再需要写原生的 POI 了,而且在数据量方面也提供了相关的解决方案。

        导入 Excel 文件示例

        文件上传的 Controller.calss 示例

    /**
     * 导入节假日管理信息
     * @param file
     */
    @PutMapping("/file" )
    public void uploadHolidays(@RequestParam("file") MultipartFile file) throws IOException {
        return HolidaysService.uploadHolidays(file);
    }

        上传过程 ServiceImpl.calss 示例

    // 上传数据,并返回上传的数据:这里有一个监听器,此监听器并非 Spring 进行管理
    public String uploadHolidays(MultipartFile file) throws IOException {
        List<ConfigureHolidaysVO> holidaysVOS = EasyExcel.read(file.getInputStream(), ConfigureHolidaysVO.class,
            new HolidaysDataListener(this)).sheet().doReadSync();
        return true;
    }

        监听器的简单示例

@Slf4j
public class HolidaysDataListener implements ReadListener<ConfigureHolidaysVO> {

    private ConfigureHolidaysService holidaysService;

    public HolidaysDataListener(ConfigureHolidaysService holidaysService) {
        this.holidaysService = holidaysService;
    }

    private static final int BATCH_COUNT    = 100;
    /**
     * 缓存的数据
     */
    private  List<ConfigureHolidaysVO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    @Override
    public void invoke(ConfigureHolidaysVO data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 确保最后遗留的数据存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        holidaysService.saveBatchHolidaysVOs(cachedDataList);
    }
}

        导出 Excel 文件示例

        文件导出的 Controller.calss 示例

    /**
     * 导出节假日管理信息
     * @param response
     */
    @GetMapping("/{year}/file" )
    public void downloadHolidays(HttpServletResponse response, @PathVariable String year) throws IOException {
        HolidaysService.downloadHolidays(year, response);
    }

        导出过程 ServiceImpl.calss 示例:当直接把数据流写入 HttpServletResponse 时,就可以直接在浏览器中下载导出的文件,当然也可以把文件写入到指定的路径,详情请查阅文档。

    /**
     * 数据导出
     */
    public void downloadHolidays(String year, HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(year + "年节假日数据导出", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ConfigureHolidaysVO.class).sheet(year).doWrite(holidaysData(year));
    }

    /**
     * 获取存储在数据库中的节假日数据
     * @param year
     * @return
     */
    private List<ConfigureHolidaysVO> holidaysData(String year) {
        return list(
            Wrappers.lambdaQuery(ConfigureHolidays.class).eq(ConfigureHolidays::getAdjustYear, year))
            .stream().map(r -> {
                ConfigureHolidaysVO vo = new ConfigureHolidaysVO();
                BeanUtils.copyProperties(r, vo);
                List<Integer> dayList = JSON.parseObject(r.getAdjustDays(), List.class);
                vo.setAdjustDays(dayList);
                return vo;
            }).sorted(Comparator.comparing(e -> Integer.valueOf(e.getAdjustMonth()))).collect(Collectors.toList());
    }

        因为节假日的导入导出重点在于 POI 操作 ,并非本文重点,有关更加详细的 POI 操作请查阅 easy excel 文档。


版权声明:本文为swadian2008原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。