一些项目中会有日历或日期设置,最基本的会显示工作日,休息日,节假日等等,下面就是基于项目中的日历管理功能,要显示工作日,休息日,节假日
效果图
获取国家法定节假日工具类
public class HolidayUtils {private static Logger logger = LoggerFactory.getLogger(HolidayUtils.class);public static Map<String,Map<String,OtherData>> monthToHolidayDate = new ConcurrentHashMap<>(12);public static Map<String,OtherData> dateToOtherData = new ConcurrentHashMap<>(12);public static void main(String[] args) {System.out.println(getAllHoliday(2024));}/*** 获取周末和节假日** @param year* @return*/public static List<String> getAllHoliday(int year) {// 获取所有的周末Set<String> allWeekend = getAllWeekend(year);// http://timor.tech/api/holiday api文档地址Map apiHoliday = getApiHoliday(year);Integer code = (Integer) apiHoliday.get("code");if (code != 0) {return null;}Map<String, Map<String, Object>> holiday = (Map<String, Map<String, Object>>) apiHoliday.get("holiday");Set<String> strings = holiday.keySet();for (String str : strings) {Map<String, Object> stringObjectMap = holiday.get(str);Integer wage = (Integer) stringObjectMap.get("wage");String date = (String) stringObjectMap.get("date");//筛选掉补班if (wage.equals(1)) {allWeekend.remove(date);} else {allWeekend.add(date);}int monthByDate = CalendarUtils.getMonthByDate(CalendarUtils.parseDateStrToDate(date, "yyyy-MM-dd"));if (!monthToHolidayDate.containsKey(monthByDate)){monthToHolidayDate.put(monthByDate+"",new HashMap<>());}Map<String, OtherData> dateToOtherData = monthToHolidayDate.get(monthByDate);if (dateToOtherData == null) dateToOtherData = new HashMap<>();if (!dateToOtherData.containsKey(date)){OtherData otherData = new OtherData();otherData.putAll(stringObjectMap);dateToOtherData.put(date,otherData);dateToOtherData.put(date,otherData);}}List<String> result = new ArrayList<>(allWeekend);result = result.stream().sorted().collect(Collectors.toList());return result;}/*** 获取节假日不含周末** @param year* @return*/private static Map getApiHoliday(int year) {String url = "http://timor.tech/api/holiday/year/" + year;String rsa = HttpUtil.get(url);logger.info("rsa:{}",rsa);Map map = JsonConverter.jsonStrToObject(rsa, Map.class);return map;}/*** 获取周末 月从0开始** @param year* @return*/public static Set<String> getAllWeekend(int year) {Set<String> dateList = new HashSet<>();SimpleDateFormat simdf = new SimpleDateFormat("yyyy-MM-dd");Calendar calendar = new GregorianCalendar(year, 0, 1);Calendar endCalendar = new GregorianCalendar(year, 11, 31);while (true) {int weekday = calendar.get(Calendar.DAY_OF_WEEK);if (weekday == 1 || weekday == 7) {dateList.add(simdf.format(calendar.getTime()));}calendar.add(Calendar.DATE, 1);if (calendar.getTimeInMillis() >= endCalendar.getTimeInMillis()) {break;}}return dateList;}public static Map<String,OtherData> getHolidayByMonth(String month,Date date){if (monthToHolidayDate == null) return new HashMap<>();if (StringUtils.isNotBlank(month)){month = CalendarUtils.getMonthByDate(date) + "";Map<String, OtherData> dateToOtherData = monthToHolidayDate.get(month);if (dateToOtherData == null) dateToOtherData = new HashMap<>();return dateToOtherData;}return new HashMap<>();}public static OtherData getHolidayByDate(Date date){String month = CalendarUtils.getMonthByDate(date) + "";Map<String, OtherData> dateToOtherData = monthToHolidayDate.get(month);if (dateToOtherData == null || dateToOtherData.size() == 0) return null;String dateStr = CalendarUtils.toString(date, "yyyy-MM-dd");OtherData otherData = dateToOtherData.get(dateStr);if (otherData != null && otherData.obtainVal("wage",Integer.class) != null&& 1 == otherData.obtainVal("wage",Integer.class)){return null;}return otherData;}public static String isHoliday(Date date){String month = CalendarUtils.getMonthByDate(date) + "";Map<String, OtherData> dateToOtherData = monthToHolidayDate.get(month);if (dateToOtherData == null || dateToOtherData.size() == 0) return null;String dateStr = CalendarUtils.toString(date, "yyyy-MM-dd");OtherData otherData = dateToOtherData.get(dateStr);if (otherData == null) return null;if (otherData != null && otherData.obtainVal("wage",Integer.class) != null&& 1 == otherData.obtainVal("wage",Integer.class)){return DateRec.DATE_TYPE_WORK;}return DateRec.DATE_TYPE_HOLIDAY;}}
返回的JSON数据格式
{"code": 0,"holiday": {"01-01": {"holiday": true,"name": "元旦","wage": 3,"date": "2024-01-01","rest": 1},"02-04": {"holiday": false,"name": "春节前补班","wage": 1,"after": false,"target": "春节","date": "2024-02-04","rest": 9},"02-10": {"holiday": true,"name": "初一","wage": 3,"date": "2024-02-10","rest": 15},"02-11": {"holiday": true,"name": "初二","wage": 3,"date": "2024-02-11","rest": 1},"02-12": {"holiday": true,"name": "初三","wage": 3,"date": "2024-02-12"},"02-13": {"holiday": true,"name": "初四","wage": 2,"date": "2024-02-13"},"02-14": {"holiday": true,"name": "初五","wage": 2,"date": "2024-02-14"},"02-15": {"holiday": true,"name": "初六","wage": 2,"date": "2024-02-15"},"02-16": {"holiday": true,"name": "初七","wage": 2,"date": "2024-02-16"},"02-17": {"holiday": true,"name": "初八","wage": 2,"date": "2024-02-17"},"02-18": {"holiday": false,"name": "春节后补班","wage": 1,"after": true,"target": "春节","date": "2024-02-18"},"04-04": {"holiday": true,"name": "清明节","wage": 3,"date": "2024-04-04","rest": 46},"04-05": {"holiday": true,"name": "清明节","wage": 2,"date": "2024-04-05"},"04-06": {"holiday": true,"name": "清明节","wage": 2,"date": "2024-04-06"},"04-07": {"holiday": false,"name": "清明节后补班","wage": 1,"target": "清明节","after": true,"date": "2024-04-07"},"04-28": {"holiday": false,"name": "劳动节前补班","wage": 1,"target": "劳动节","after": false,"date": "2024-04-28"},"05-01": {"holiday": true,"name": "劳动节","wage": 3,"date": "2024-05-01"},"05-02": {"holiday": true,"name": "劳动节","wage": 2,"date": "2024-05-02","rest": 1},"05-03": {"holiday": true,"name": "劳动节","wage": 3,"date": "2024-05-03"},"05-04": {"holiday": true,"name": "劳动节","wage": 3,"date": "2024-05-04"},"05-05": {"holiday": true,"name": "劳动节","wage": 3,"date": "2024-05-05"},"05-11": {"holiday": false,"name": "劳动节后补班","after": true,"wage": 1,"target": "劳动节","date": "2024-05-11"},"06-08": {"holiday": true,"name": "端午节","wage": 2,"date": "2024-06-08"},"06-09": {"holiday": true,"name": "端午节","wage": 2,"date": "2024-06-09"},"06-10": {"holiday": true,"name": "端午节","wage": 3,"date": "2024-06-10"},"09-14": {"holiday": false,"name": "中秋节前补班","after": false,"wage": 1,"target": "中秋节","date": "2024-09-14","rest": 96},"09-15": {"holiday": true,"name": "中秋节","wage": 2,"date": "2024-09-15","rest": 97},"09-16": {"holiday": true,"name": "中秋节","wage": 2,"date": "2024-09-16"},"09-17": {"holiday": true,"name": "中秋节","wage": 3,"date": "2024-09-17"},"09-29": {"holiday": false,"name": "国庆节前补班","after": false,"wage": 1,"target": "国庆节","date": "2024-09-29"},"10-01": {"holiday": true,"name": "国庆节","wage": 3,"date": "2024-10-01"},"10-02": {"holiday": true,"name": "国庆节","wage": 3,"date": "2024-10-02","rest": 1},"10-03": {"holiday": true,"name": "国庆节","wage": 3,"date": "2024-10-03"},"10-04": {"holiday": true,"name": "国庆节","wage": 2,"date": "2024-10-04"},"10-05": {"holiday": true,"name": "国庆节","wage": 2,"date": "2024-10-05"},"10-06": {"holiday": true,"name": "国庆节","wage": 2,"date": "2024-10-06","rest": 1},"10-07": {"holiday": true,"name": "国庆节","wage": 2,"date": "2024-10-07","rest": 1},"10-12": {"holiday": false,"after": true,"wage": 1,"name": "国庆节后补班","target": "国庆节","date": "2024-10-12"}}
}
实体模型
@Entity
@Table(name = "t_daterec",indexes={@Index(name="idx_t_daterec1",columnList="dateType"),@Index(name="idx_t_daterec2",columnList="dateTime")}
)
public class DateRec extends ExBizEntity {public static final String DATE_TYPE_WORK = "work";public static final String DATE_TYPE_WEEKEND = "weekend";public static final String DATE_TYPE_HOLIDAY = "holiday";@Column(length=20,nullable=false)private String dateType;//日历类型private Date dateTime;//日期public String getDateType() {return dateType;}public Date getDateTime() {return dateTime;}public DateRec() {}public DateRec(String id,String dateType, Date dateRTime) {this.id = id;this.dateType = dateType;this.dateTime = dateTime;}
}
@Entity
@Table(name = "t_holiday",indexes={@Index(name="idx_t_holiday1",columnList="holidayDate")}
)
public class Holiday extends ExBizEntity{private Date holidayDate;public Holiday() {}public Holiday(Date holidayDate) {this.holidayDate = holidayDate;}public Date getHolidayDate() {return holidayDate;}
}
超类
@MappedSuperclass
public abstract class ExBizEntity extends ValueObjectEntity {@Type(type="com.xysd.common.utils.hibernateType.MyCustomJsonType")private OtherData exAttr = new OtherData();//额外属性mappublic OtherData getExAttr() {return exAttr;}protected ExBizEntity(){super();}protected ExBizEntity(Map<String, Object> exAttr) {super();this.getNotNullExAttrWithUpdate().putAll(exAttr);}//获取非空扩展属性private OtherData getNotNullExAttrWithUpdate() {if(this.exAttr == null) this.exAttr = new OtherData();return this.exAttr;}public void clearExAttr(){this.exAttr = null;}//更新扩展属性public void updateExAttr(Map<String, Object> exAttr){this.getNotNullExAttrWithUpdate().clear();if(exAttr==null) {this.exAttr = null;return;}this.addAttrs(exAttr);}//添加扩展属性public void addAttr(String key, Object value){if(StringUtils.isBlank(key)) return;if(value==null) {this.getNotNullExAttrWithUpdate().remove(key);}else {this.getNotNullExAttrWithUpdate().put(key, value);}}//添加扩展属性public void addAttrs(Map<String, Object> exAttr){if(exAttr==null) return;for (Map.Entry<String,Object> e : exAttr.entrySet()) {this.addAttr(e.getKey(), e.getValue());}}//获取指定类型的对象@Transientpublic <T> T getAttr(String key) {if(this.exAttr==null) return null;return this.exAttr.obtainVal(key);}//获取指定类型的对象@Transientpublic <T> T getAttr(String key, Class<T> valClass) {if(this.exAttr==null) return null;return this.exAttr.obtainVal(key, valClass);}//获取指定转换类型的对象@Transientpublic <T> T getAttr(String key, TypeReference<T> valTypeRef) {if(this.exAttr==null) return null;return this.exAttr.obtainVal(key, valTypeRef);}}
@MappedSuperclass
public abstract class ValueObjectEntity extends IEntity{public static String SYSCODE_CAD="cad";//系统编码-cad:cad接口protected Date createTime = new Date();//创建时间@Type(type = "org.hibernate.type.NumericBooleanType")protected boolean history=false;@Column(length=40)protected String createIp;//创建时的ipprotected int valid=1;//有效性protected Date lastUpdateDate = new Date();//最后更新时间@Column(length=10)protected String syscode=SYSCODE_HDXF; //数据系统编码public Date getCreateTime() {return createTime;}public boolean isHistory() {return history;}public String getCreateIp() {return createIp;}public int getValid() {return valid;}public Date getLastUpdateDate() {return lastUpdateDate;}public String getSyscode() {return syscode;}protected ValueObjectEntity() {super();}@Transientpublic boolean isValidEntity(){return this.getValid()==1;}public void updateValid(int valid){this.valid = valid;}}
@MappedSuperclass
public abstract class IEntity {@Id@Column(length=100)@GeneratedValue(generator="uuidkey")@GenericGenerator(name="uuidkey", strategy = "com.xysd.common.utils.BaseIDGenerator")protected String id;public String getId() {return this.id;}/*** 对比俩个实体是否是同一个*/public boolean compareObject(IEntity other) {return other != null && new EqualsBuilder().append(this.id, other.getId()).isEquals();}}
public class BaseIDGenerator implements IdentifierGenerator {private static AutoIncrementIdUtil autoIncrementIdUtil;public static void registAutoIncrementIdUtil(AutoIncrementIdUtil autoIncrementIdUtil){BaseIDGenerator.autoIncrementIdUtil = autoIncrementIdUtil;}@Overridepublic Serializable generate(SharedSessionContractImplementor arg0,Object o) throws HibernateException {if(o instanceof NeedAutoIncrementId){NeedAutoIncrementId entity = (NeedAutoIncrementId) o;String id = entity.obtainId();if(!StringUtils.isEmpty(id)){entity.initId(id);}else {id = autoIncrementIdUtil.getId(entity.getClass().getSimpleName(), entity.obtainParentId(),entity.obtainLength(), entity.obtainSeparator());entity.initId(id);}return id;}if(o instanceof IEntity){//允许自己指定IDIEntity be = (IEntity)o;if(StringUtils.isNotBlank(be.getId())){return be.getId();}}return Utils.getUUID("");}
}
接口
@ApiOperation(value="日历管理查看",httpMethod="GET")@ApiImplicitParams({@ApiImplicitParam(name="year",value="年份",required=true),@ApiImplicitParam(name="month",value="月份",required=true)})@RequestMapping(value = "/dates/list", method = RequestMethod.GET)public String getDates(@RequestParam int year, @RequestParam int month, HttpServletRequest hreq) {String weeks = myService.getDates(year,month);return weeks;}}
Service服务及封装数据
@Service
public class MyService {@Autowiredprivate DateRecRepositoryHibernate dateRecRepositoryHibernate;@PostConstructpublic void init(){//加载国家法定节假日HolidayUtils.getAllHoliday(CalendarUtils.getCurrentYear());Map<String, OtherData> dateToOtherData = HolidayUtils.dateToOtherData;List<Holiday> holidays = this.dateRecRepositoryHibernate.getHolidays();if (CollectionUtils.isNotEmpty(holidays)) {for (Holiday holiday : holidays) {HolidayUtils.dateToOtherData.put(CalendarUtils.toString(holiday.getHolidayDate(), "yyyy-MM-dd"), holiday.getExAttr());}} else {for (Map.Entry<String, OtherData> entry : dateToOtherData.entrySet()) {Holiday h = new Holiday(CalendarUtils.parseDateStrToDate(entry.getKey(), "yyyy-MM-dd"));h.addAttrs(entry.getValue());this.dateRecRepositoryHibernate.createOrUpdateHoliday(h);}}}public String getDates(int year, int month) {//要返回前端展示使用List<WeekDTO> weeks = new ArrayList<WeekDTO>();//获取year年month月的第一天Date monthBegin = CalendarUtils.getMonthBeginByYearAndMonth(year, month);//获取year年month月的最后一天Date monthEnd = CalendarUtils.getMonthEndByYearAndMonth(year, month);WeekValObj wo = CalendarUtils.getWeekValObjByDateOfYear(monthBegin);//获取year年month月的第一天是这一年中第几周int weekNumOfMonthBegin = wo.getWeek();//selectYear就是yearint selectedYear = wo.getYear();Map<String, DateDTO> allDates = new HashMap<String, DateDTO>();List<String> dates = new ArrayList<String>();int weekNum = 7;for (int k = 0; k < weekNum; k++) {//获取selectyear年总共有几周int maxWeekOfYear = CalendarUtils.getMaxWeekCountByYear(selectedYear);//获取selectedYear年第weekNumOfMonthBegin周的第一天日期Date weekBegin = CalendarUtils.getWeekBeginByYearAndWeek(selectedYear, weekNumOfMonthBegin);List<DateDTO> weekDates = new ArrayList<DateDTO>();if (weekBegin == null) {//如果没有获取到 则默认为year+1年的第一周的第一天日期weekBegin = CalendarUtils.getWeekBeginByYearAndWeek(year + 1, 1);}if (weekBegin != null && weekBegin.getTime() < monthEnd.getTime()) {for (int i = 0; i < 7; i++) {//开始取第weekNumOfMonthBegin周的第i天Date d = DateUtils.addDays(weekBegin, i);String type = null;if (StringUtils.isNotBlank(HolidayUtils.isHoliday(d))) {type = HolidayUtils.isHoliday(d);} else {type = DateRec.DATE_TYPE_WORK;if (i >= 5) {type = DateRec.DATE_TYPE_WEEKEND;}}//是否要展示boolean display = d.getTime() >= monthBegin.getTime() && d.getTime() <= monthEnd.getTime();String dateStr = CalendarUtils.toString(d, "yyyy-MM-dd");DateDTO dateDTO = new DateDTO(dateStr, type, display);weekDates.add(dateDTO);allDates.put(dateDTO.getDate(), dateDTO);}weeks.add(new WeekDTO(year, weekNumOfMonthBegin, weekDates));}if (weekNumOfMonthBegin >= maxWeekOfYear) {selectedYear++;weekNumOfMonthBegin = 1;} else {weekNumOfMonthBegin++;}}dates.addAll(allDates.keySet());Map<String, Object> params = new HashMap<>();params.put("dates", dates);List<DateRec> existedDateRecs = this.dateRecRepositoryHibernate.getDateRecBy(params);for (DateRec drec : existedDateRecs) {//已存在的DateDTO dto = allDates.remove(drec.getId());if (dto != null) {dto.setDateType(drec.getDateType());}}for (DateDTO dto : allDates.values()) {//需要创建的DateRec drec = new DateRec(dto.getDate(),dto.getDateType(), CalendarUtils.parseDateStrToDate(dto.getDate(), "yyyy-MM-dd"));this.dateRecRepositoryHibernate.createOrUpdateDateRec(drec);}return JsonConverter.toJsonStr(weeks);}}
数据基础层
@Repository
public class DateRecRepositoryHibernate extends JpaHibernateRepository {public void createOrUpdateDateRec(DateRec dateRec){this.getSession().saveOrUpdate(dateRec);}public List<DateRec> getDateRecBy(Map<String,Object> params){StringBuffer sql = new StringBuffer();sql.append(" select id from t_daterec where valid = 1 ");if (params.get("ids") != null){sql.append(" and id in (:ids) ");}if (params.get("dates") != null){sql.append(" and date in (:dates) ");}if (params.get("dateTypes") != null){sql.append(" and date_type in (:dateTypes) ");}List<String> ids = this.createSQLQueryByMapParams(sql.toString(), params).list();if (CollectionUtils.isEmpty(ids)) return new ArrayList<>();List<DateRec> recs = this.findByOrderedIds(DateRec.class, ids);if (recs == null) return new ArrayList<>();return recs;}public void createOrUpdateHoliday(Holiday holiday){this.getSession().saveOrUpdate(holiday);}public List<Holiday> getHolidays(){String sql = "select d from " + Holiday.class.getName() + " d where d.holidayDate >= : begin and d.holidayDate <= :end ";List<Holiday> list = this.createHQLQueryByMapParams(Holiday.class, sql, Utils.buildMap("begin", CalendarUtils.getCurrentYearBeginDate(), "end", CalendarUtils.getCurrentYearEndDate())).list();if (list == null) list = new ArrayList<>();return list;}
}
请求返回值
[{"year": 2024,"weekNum": 5,"dates": [{"date": "2024-01-29","dateType": "work","display": false},{"date": "2024-01-30","dateType": "work","display": false},{"date": "2024-01-31","dateType": "work","display": false},{"date": "2024-02-01","dateType": "work","display": true},{"date": "2024-02-02","dateType": "work","display": true},{"date": "2024-02-03","dateType": "weekend","display": true},{"date": "2024-02-04","dateType": "weekend","display": true}]},{"year": 2024,"weekNum": 6,"dates": [{"date": "2024-02-05","dateType": "work","display": true},{"date": "2024-02-06","dateType": "work","display": true},{"date": "2024-02-07","dateType": "work","display": true},{"date": "2024-02-08","dateType": "work","display": true},{"date": "2024-02-09","dateType": "work","display": true},{"date": "2024-02-10","dateType": "weekend","display": true},{"date": "2024-02-11","dateType": "weekend","display": true}]},{"year": 2024,"weekNum": 7,"dates": [{"date": "2024-02-12","dateType": "work","display": true},{"date": "2024-02-13","dateType": "work","display": true},{"date": "2024-02-14","dateType": "work","display": true},{"date": "2024-02-15","dateType": "work","display": true},{"date": "2024-02-16","dateType": "work","display": true},{"date": "2024-02-17","dateType": "weekend","display": true},{"date": "2024-02-18","dateType": "weekend","display": true}]},{"year": 2024,"weekNum": 8,"dates": [{"date": "2024-02-19","dateType": "work","display": true},{"date": "2024-02-20","dateType": "work","display": true},{"date": "2024-02-21","dateType": "work","display": true},{"date": "2024-02-22","dateType": "work","display": true},{"date": "2024-02-23","dateType": "work","display": true},{"date": "2024-02-24","dateType": "weekend","display": true},{"date": "2024-02-25","dateType": "weekend","display": true}]},{"year": 2024,"weekNum": 9,"dates": [{"date": "2024-02-26","dateType": "work","display": true},{"date": "2024-02-27","dateType": "work","display": true},{"date": "2024-02-28","dateType": "work","display": true},{"date": "2024-02-29","dateType": "work","display": true},{"date": "2024-03-01","dateType": "work","display": false},{"date": "2024-03-02","dateType": "weekend","display": false},{"date": "2024-03-03","dateType": "weekend","display": false}]}
]