万年历API:https://www.mxnzp.com/doc/detail?id=1
package com.qiangesoft.calendar.mxnzp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiangesoft.calendar.entity.CalendarConfig;
import com.qiangesoft.calendar.service.CalendarConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
/**
* 日历数据生成 定时器执行者
*
* @author qiangesoft
* @date 2023-09-29
*/
@Slf4j
@Component
public class CalendarTask {
@Autowired
private CalendarConfigService calendarConfigService;
/**
* 规则可设置为每日或者每月执行一次
*/
@Scheduled(cron = "0 0 10 * * ?")
public void action() {
log.info("Create calendar data start======================>");
// 生成未来五年的数据
LocalDate thisYearFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
for (int i = 0; i < 5; i++) {
LocalDate localDate = thisYearFirstDay.plusYears(i);
this.doCreate(localDate);
}
log.info("Create calendar data finish<======================");
}
/**
* 日历数据生成
*
* @param firstDay
*/
private void doCreate(LocalDate firstDay) {
int year = firstDay.getYear();
log.info("Create {}year calendar data start!", year);
LambdaQueryWrapper<CalendarConfig> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CalendarConfig::getYear, year);
long count = calendarConfigService.count(queryWrapper);
if (count > 0) {
log.info("Calendar data already created, do nothing!");
return;
}
LocalDate lastDay = firstDay.plusYears(1);
List<CalendarConfig> calendarConfigList = new ArrayList<>();
LocalDate localDate = firstDay;
while (lastDay.isAfter(localDate)) {
CalendarConfig calendarConfig = new CalendarConfig();
calendarConfig.setYear(year);
calendarConfig.setMonth(localDate.getMonthValue());
calendarConfig.setDate(localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
int week = localDate.getDayOfWeek().getValue();
calendarConfig.setWeekDay(week);
if (week == 6 || week == 7) {
calendarConfig.setType("1");
} else {
calendarConfig.setType("0");
}
calendarConfigList.add(calendarConfig);
localDate = localDate.plusDays(1);
}
calendarConfigService.saveBatch(calendarConfigList);
log.info("Create {}year calendar data finish!", year);
}
}
package com.qiangesoft.calendar.mxnzp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiangesoft.calendar.entity.CalendarConfig;
import com.qiangesoft.calendar.mxnzp.model.CalendarConfigDTO;
import com.qiangesoft.calendar.mxnzp.model.MxnzpCalendarDTO;
import com.qiangesoft.calendar.mxnzp.model.MxnzpResponseData;
import com.qiangesoft.calendar.service.CalendarConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* mxnpz数据拉取 定时器执行者
*
* @author qiangesoft
* @date 2023-09-29
*/
@Slf4j
@Component
public class MxnzpCalendarTask {
private static String URL = "https://www.mxnzp.com/api/holiday/list/year/%d?ignoreHoliday=false&app_id=tldkn1hkkoofques&app_secret=kV9qgeRJ5baZworKApsWVbHS3hNxndYZ";
@Autowired
private RestTemplate restTemplate;
@Autowired
private CalendarConfigService calendarConfigService;
/**
* 国家一般当年10月底发布下一年度的节假日安排
*/
@Scheduled(cron = "0 0 10 * * ?")
public void action() {
LocalDate today = LocalDate.now();
// 从11月开始拉取下一年的数据
int year = today.getYear();
if (today.getMonthValue() > 10) {
year = year + 1;
}
log.info("Mxnzp data pull {}year start======================>", year);
LambdaQueryWrapper<CalendarConfig> countQueryWrapper = new LambdaQueryWrapper<>();
countQueryWrapper.eq(CalendarConfig::getYear, year)
.eq(CalendarConfig::getPullFlag, true);
long count = calendarConfigService.count(countQueryWrapper);
if (count > 0) {
log.info("Mxnzp data already update, do nothing!");
return;
}
ResponseEntity<MxnzpResponseData> responseEntity = restTemplate.getForEntity(String.format(URL, year), MxnzpResponseData.class);
HttpStatus statusCode = responseEntity.getStatusCode();
if (!HttpStatus.OK.equals(statusCode)) {
log.info("Mxnzp data pull fail!");
return;
}
MxnzpResponseData responseData = responseEntity.getBody();
if (!responseData.getCode().equals(1)) {
log.info("Mxnzp data pull fail!");
return;
}
List<MxnzpCalendarDTO> data = responseData.getData();
if (CollectionUtils.isEmpty(data)) {
log.info("Mxnzp data pull is empty!");
return;
}
LambdaQueryWrapper<CalendarConfig> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CalendarConfig::getYear, year);
List<CalendarConfig> calendarConfigList = calendarConfigService.list(queryWrapper);
Map<String, CalendarConfig> configMap = calendarConfigList.stream().collect(Collectors.toMap(CalendarConfig::getDate, calendarConfig -> calendarConfig));
List<CalendarConfig> newConfigList = new ArrayList<>();
List<CalendarConfig> updateConfigList = new ArrayList<>();
for (MxnzpCalendarDTO monthData : data) {
List<CalendarConfigDTO> days = monthData.getDays();
for (CalendarConfigDTO day : days) {
CalendarConfig calendarConfig = configMap.get(day.getDate());
if (calendarConfig == null) {
calendarConfig = new CalendarConfig();
calendarConfig.setYear(monthData.getYear());
calendarConfig.setMonth(monthData.getMonth());
calendarConfig.setDate(day.getDate());
calendarConfig.setType(day.getType());
calendarConfig.setTypeDes(day.getTypeDes());
calendarConfig.setWeekDay(day.getWeekDay());
calendarConfig.setDayOfYear(day.getDayOfYear());
calendarConfig.setWeekOfYear(day.getWeekOfYear());
calendarConfig.setIndexWorkDayOfMonth(day.getIndexWorkDayOfMonth());
calendarConfig.setLunarCalendar(day.getLunarCalendar());
calendarConfig.setSolarTerms(day.getSolarTerms());
calendarConfig.setYearTips(day.getYearTips());
calendarConfig.setChineseZodiac(day.getChineseZodiac());
calendarConfig.setConstellation(day.getConstellation());
calendarConfig.setSuit(day.getSuit());
calendarConfig.setAvoid(day.getAvoid());
calendarConfig.setPullFlag(true);
newConfigList.add(calendarConfig);
} else {
calendarConfig.setType(day.getType());
calendarConfig.setTypeDes(day.getTypeDes());
calendarConfig.setWeekDay(day.getWeekDay());
calendarConfig.setDayOfYear(day.getDayOfYear());
calendarConfig.setWeekOfYear(day.getWeekOfYear());
calendarConfig.setIndexWorkDayOfMonth(day.getIndexWorkDayOfMonth());
calendarConfig.setLunarCalendar(day.getLunarCalendar());
calendarConfig.setSolarTerms(day.getSolarTerms());
calendarConfig.setYearTips(day.getYearTips());
calendarConfig.setChineseZodiac(day.getChineseZodiac());
calendarConfig.setConstellation(day.getConstellation());
calendarConfig.setSuit(day.getSuit());
calendarConfig.setAvoid(day.getAvoid());
calendarConfig.setPullFlag(true);
updateConfigList.add(calendarConfig);
}
}
}
if (!CollectionUtils.isEmpty(newConfigList)) {
calendarConfigService.saveBatch(newConfigList);
}
if (!CollectionUtils.isEmpty(updateConfigList)) {
calendarConfigService.updateBatchById(updateConfigList);
}
log.info("Mxnzp data {}year updated<========================", year);
}
}
package com.qiangesoft.calendar.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;
/**
* 日历配置
*
* @author qiangesoft
* @date 2023-10-19 22:28:02
*/
@Data
@TableName("calendar_config")
public class CalendarConfig {
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 年份
*/
private Integer year;
/**
* 月份
*/
private Integer month;
/**
* 日期
*/
private String date;
/**
* 类型
*/
private String type;
/**
* 类型描述
*/
private String typeDes;
/**
* 本周第几天
*/
private Integer weekDay;
/**
* 年中第几天
*/
private Integer dayOfYear;
/**
* 年中第几周
*/
private Integer weekOfYear;
/**
* 当月的第几个工作日
*/
private Integer indexWorkDayOfMonth;
/**
* 农历日期
*/
private String lunarCalendar;
/**
* 节气描述
*/
private String solarTerms;
/**
* 天干地支纪年法
*/
private String yearTips;
/**
* 属相
*/
private String chineseZodiac;
/**
* 星座
*/
private String constellation;
/**
* 宜事项
*/
private String suit;
/**
* 忌事项
*/
private String avoid;
/**
* 是否拉取日历数据
*/
private Boolean pullFlag;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createBy;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createUser;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/**
* 更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
}
源码地址:https://gitee.com/qiangesoft/boot-business/tree/master/boot-business-calendar