This commit is contained in:
2025-11-28 16:23:32 +08:00
commit a9e0e16c29
826 changed files with 89805 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
# blade-starter-holidays
`blade-starter-holidays` 用来判断日期是否工作日,更具 php 版修改。支持2019年起至2024年 中国法定节假日以国务院发布的公告为准随时调整及增加http://www.gov.cn/zfwj/bgtfd.htm 或 http://www.gov.cn/zhengce/xxgkzl.htm
## 使用
### maven
```xml
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-holidays</artifactId>
<version>${version}</version>
</dependency>
```
### gradle
```groovy
compile("org.springblade:blade-starter-holidays:${version}")
```
### 注入 bean
```java
@Autowired
private HolidaysApi holidaysApi;
```
### 接口使用
```java
/**
* 获取日期类型
*
* @param localDate LocalDate
* @return DaysType
*/
DaysType getDaysType(LocalDate localDate);
/**
* 获取日期类型
*
* @param localDateTime LocalDateTime
* @return DaysType
*/
DaysType getDaysType(LocalDateTime localDateTime);
/**
* 获取日期类型
*
* @param date Date
* @return DaysType
*/
DaysType getDaysType(Date date);
/**
* 判断是否工作日
*
* @param localDate LocalDate
* @return 是否工作日
*/
boolean isWeekdays(LocalDate localDate);
/**
* 判断是否工作日
*
* @param localDateTime LocalDateTime
* @return 是否工作日
*/
boolean isWeekdays(LocalDateTime localDateTime);
/**
* 判断是否工作日
*
* @param date Date
* @return 是否工作日
*/
boolean isWeekdays(Date date);
```
## 链接
- holidays_api PHP 版https://gitee.com/web/holidays_api

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>BladeX-Tool</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<artifactId>blade-starter-holidays</artifactId>
<name>${project.artifactId}</name>
<version>${project.parent.version}</version>
<packaging>jar</packaging>
<dependencies>
<!-- Blade -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-tool</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<scope>provided</scope>
</dependency>
<!-- Auto -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-auto</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.core.holidays.config;
import org.springblade.core.holidays.core.HolidaysApi;
import org.springblade.core.holidays.impl.HolidaysApiImpl;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ResourceLoader;
/**
* 配置
*
* @author L.cm
*/
@AutoConfiguration
@EnableConfigurationProperties(HolidaysApiProperties.class)
public class HolidaysApiConfiguration {
@Bean
public HolidaysApi holidaysApi(ResourceLoader resourceLoader,
HolidaysApiProperties properties) {
return new HolidaysApiImpl(resourceLoader, properties);
}
}

View File

@@ -0,0 +1,67 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.core.holidays.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import java.util.ArrayList;
import java.util.List;
/**
* HolidaysApi 配置类
*
* @author L.cm
*/
@Getter
@Setter
@RefreshScope
@ConfigurationProperties(HolidaysApiProperties.PREFIX)
public class HolidaysApiProperties {
public static final String PREFIX = "mica.holidays";
/**
* 自行扩展的 json 文件路径
*/
private List<ExtData> extData = new ArrayList<>();
@Getter
@Setter
public static class ExtData {
/**
* 年份
*/
private Integer year;
/**
* 数据目录
*/
private String dataPath;
}
}

View File

@@ -0,0 +1,77 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.core.holidays.core;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 日期类型,工作日对应结果为 0, 休息日对应结果为 1, 节假日对应的结果为 2
*
* @author L.cm
*/
@Getter
@RequiredArgsConstructor
public enum DaysType {
/**
* 工作日
*/
WEEKDAYS((byte) 0),
/**
* 休息日
*/
REST_DAYS((byte) 1),
/**
* 节假日
*/
HOLIDAYS((byte) 2);
@JsonValue
private final byte type;
/**
* 将 type 转换成枚举
*
* @param type type
* @return DaysType
*/
public static DaysType from(byte type) {
switch (type) {
case 0:
return WEEKDAYS;
case 1:
return REST_DAYS;
case 2:
return HOLIDAYS;
default:
throw new IllegalArgumentException("未知的 DaysType:" + type);
}
}
}

View File

@@ -0,0 +1,99 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.core.holidays.core;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
/**
* 节假日接口
*
* @author L.cm
*/
public interface HolidaysApi {
/**
* 获取日期类型
*
* @param localDate LocalDate
* @return DaysType
*/
DaysType getDaysType(LocalDate localDate);
/**
* 获取日期类型
*
* @param localDateTime LocalDateTime
* @return DaysType
*/
default DaysType getDaysType(LocalDateTime localDateTime) {
return getDaysType(localDateTime.toLocalDate());
}
/**
* 获取日期类型
*
* @param date Date
* @return DaysType
*/
default DaysType getDaysType(Date date) {
return getDaysType(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
}
/**
* 判断是否工作日
*
* @param localDate LocalDate
* @return 是否工作日
*/
default boolean isWeekdays(LocalDate localDate) {
return DaysType.WEEKDAYS.equals(getDaysType(localDate));
}
/**
* 判断是否工作日
*
* @param localDateTime LocalDateTime
* @return 是否工作日
*/
default boolean isWeekdays(LocalDateTime localDateTime) {
return DaysType.WEEKDAYS.equals(getDaysType(localDateTime));
}
/**
* 判断是否工作日
*
* @param date Date
* @return 是否工作日
*/
default boolean isWeekdays(Date date) {
return DaysType.WEEKDAYS.equals(getDaysType(date));
}
}

View File

@@ -0,0 +1,113 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.core.holidays.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.holidays.config.HolidaysApiProperties;
import org.springblade.core.holidays.core.DaysType;
import org.springblade.core.holidays.core.HolidaysApi;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 节假日实现
*
* @author L.cm
*/
@Slf4j
@RequiredArgsConstructor
public class HolidaysApiImpl implements HolidaysApi, InitializingBean {
/**
* 存储节假日
*/
private static final Map<Integer, Map<String, Byte>> YEAR_DATA_MAP = new HashMap<>();
private final ResourceLoader resourceLoader;
private final HolidaysApiProperties properties;
@Override
public DaysType getDaysType(LocalDate localDate) {
int year = localDate.getYear();
Map<String, Byte> dataMap = YEAR_DATA_MAP.get(year);
// 对于没有数据的,我们按正常的周六日来判断,
if (dataMap == null) {
log.error("没有对应年:[{}]的数据,请升级或者自行维护数据!", year);
return isWeekDay(localDate);
}
// 日期信息
int monthValue = localDate.getMonthValue();
int dayOfMonth = localDate.getDayOfMonth();
// 月份和日期
String monthAndDay = String.format("%02d%02d", monthValue, dayOfMonth);
Byte result = dataMap.get(monthAndDay);
if (result != null) {
return DaysType.from(result);
} else {
return isWeekDay(localDate);
}
}
@Override
public void afterPropertiesSet() throws Exception {
int[] years = new int[]{2019, 2020, 2021, 2022, 2023, 2024};
for (int year : years) {
Resource resource = resourceLoader.getResource("classpath:data/" + year + "_data.json");
try (InputStream inputStream = resource.getInputStream()) {
Map<String, Byte> dataMap = JsonUtil.readMap(inputStream, Byte.class);
YEAR_DATA_MAP.put(year, dataMap);
}
}
List<HolidaysApiProperties.ExtData> extDataList = properties.getExtData();
for (HolidaysApiProperties.ExtData extData : extDataList) {
String dataPath = extData.getDataPath();
Resource resource = resourceLoader.getResource(dataPath);
try (InputStream inputStream = resource.getInputStream()) {
Map<String, Byte> dataMap = JsonUtil.readMap(inputStream, Byte.class);
YEAR_DATA_MAP.put(extData.getYear(), dataMap);
}
}
}
/**
* 判断是否工作日
*
* @param localDate LocalDate
* @return DaysType
*/
private static DaysType isWeekDay(LocalDate localDate) {
int week = localDate.getDayOfWeek().getValue();
return week == 6 || week == 7 ? DaysType.REST_DAYS : DaysType.WEEKDAYS;
}
}

View File

@@ -0,0 +1,36 @@
{
"0101":2,
"0204":1,
"0205":2,
"0206":2,
"0207":2,
"0208":1,
"0209":1,
"0210":1,
"0405":2,
"0406":1,
"0407":1,
"0501":2,
"0502":1,
"0503":1,
"0504":1,
"0607":2,
"0608":1,
"0609":1,
"0913":2,
"0914":1,
"0915":1,
"1001":2,
"1002":2,
"1003":2,
"1004":1,
"1005":1,
"1006":1,
"1007":1,
"0202":0,
"0203":0,
"0428":0,
"0505":0,
"0929":0,
"1012":0
}

View File

@@ -0,0 +1,36 @@
{
"0101":2,
"0124":1,
"0125":2,
"0126":2,
"0127":2,
"0128":1,
"0129":1,
"0130":1,
"0404":2,
"0405":1,
"0406":1,
"0501":2,
"0502":1,
"0503":1,
"0504":1,
"0505":1,
"0625":2,
"0626":1,
"0627":1,
"1001":2,
"1002":2,
"1003":2,
"1004":2,
"1005":1,
"1006":1,
"1007":1,
"1008":1,
"0119":0,
"0201":0,
"0426":0,
"0509":0,
"0628":0,
"0927":0,
"1010":0
}

View File

@@ -0,0 +1,40 @@
{
"0101":2,
"0102":1,
"0103":1,
"0211":1,
"0212":2,
"0213":2,
"0214":2,
"0215":1,
"0216":1,
"0217":1,
"0403":1,
"0404":2,
"0405":1,
"0501":2,
"0502":1,
"0503":1,
"0504":1,
"0505":1,
"0612":1,
"0613":1,
"0614":2,
"0919":1,
"0920":1,
"0921":2,
"1001":2,
"1002":2,
"1003":2,
"1004":1,
"1005":1,
"1006":1,
"1007":1,
"0207":0,
"0220":0,
"0425":0,
"0508":0,
"0918":0,
"0926":0,
"1009":0
}

View File

@@ -0,0 +1,41 @@
{
"0101":2,
"0102":1,
"0103":1,
"0131":1,
"0201":2,
"0202":2,
"0203":2,
"0204":1,
"0205":1,
"0206":1,
"0403":1,
"0404":1,
"0405":2,
"0430":1,
"0501":2,
"0502":1,
"0503":1,
"0504":1,
"0603":2,
"0604":1,
"0605":1,
"0910":2,
"0911":1,
"0912":1,
"1001":2,
"1002":2,
"1003":2,
"1004":1,
"1005":1,
"1006":1,
"1007":1,
"0129":0,
"0130":0,
"0402":0,
"0424":0,
"0507":0,
"1008":0,
"1009":0,
"1231":1
}

View File

@@ -0,0 +1,35 @@
{
"0101":2,
"0102":1,
"0121":1,
"0122":2,
"0123":2,
"0124":2,
"0125":1,
"0126":1,
"0127":1,
"0405":2,
"0429":1,
"0430":1,
"0501":2,
"0502":1,
"0503":1,
"0622":2,
"0623":1,
"0624":1,
"0929":2,
"0930":1,
"1001":2,
"1002":2,
"1003":2,
"1004":1,
"1005":1,
"1006":1,
"0128":0,
"0129":0,
"0423":0,
"0506":0,
"0625":0,
"1007":0,
"1008":0
}

View File

@@ -0,0 +1,40 @@
{
"0101":2,
"0210":2,
"0211":2,
"0212":2,
"0213":1,
"0214":1,
"0215":1,
"0216":1,
"0217":1,
"0404":2,
"0405":1,
"0406":1,
"0501":2,
"0502":1,
"0503":1,
"0504":1,
"0505":1,
"0608":1,
"0609":1,
"0610":2,
"0915":1,
"0916":1,
"0917":2,
"1001":2,
"1002":2,
"1003":2,
"1004":1,
"1005":1,
"1006":1,
"1007":1,
"0204":0,
"0218":0,
"0407":0,
"0428":0,
"0511":0,
"0914":0,
"0929":0,
"1012":0
}

View File

@@ -0,0 +1,35 @@
package org.springblade.core.holidays.test;
import org.springblade.core.holidays.config.HolidaysApiConfiguration;
import org.springblade.core.holidays.config.HolidaysApiProperties;
import org.springblade.core.holidays.core.DaysType;
import org.springblade.core.holidays.core.HolidaysApi;
import org.springblade.core.holidays.impl.HolidaysApiImpl;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.time.LocalDate;
class HolidaysApiTest {
private HolidaysApi holidaysApi;
@BeforeEach
public void setup() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
HolidaysApiConfiguration configuration = new HolidaysApiConfiguration();
holidaysApi = configuration.holidaysApi(context, new HolidaysApiProperties());
((HolidaysApiImpl) holidaysApi).afterPropertiesSet();
}
@Test
void test() {
DaysType daysType = holidaysApi.getDaysType(LocalDate.of(2023, 1, 1));
Assertions.assertEquals(DaysType.HOLIDAYS, daysType);
Assertions.assertFalse(holidaysApi.isWeekdays(LocalDate.of(2023, 9, 29)));
Assertions.assertTrue(holidaysApi.isWeekdays(LocalDate.of(2023, 10, 7)));
}
}