使用Calendar实现自定义规则生成动态日期
1、支持配置的规则、配置含义
配置规则:Y(年)、M(月)、W(周)、D(日)
配置字段:subjectStart(标的开始类型)、subjectEnd(标的结束类型)
配置含义:如subjectStart(Y+1),subjectEnd(Y+1)-->从当前年份的次年1月1日开始,执行周期为一年,到次年年底结束的日期。如subjectStart(M-3),subjectEnd(M+4)-->从当前月份的前3个月开始,到执行周期为4个月结束的日期,依次类推。
支持通过提供开始日期,根据配置规则生成结束日期
2、根据配置规则,生成对应的开始、结束日期。看代码
/**
* 根据配置的规则,生成默认的开始日期、标的结束日期
* 通过标的约束时段计算日期
*
* @param model
* @return
*/
public BaseResponse computeDefaultTargetDate(DynamicDateVO model) {
if(StringUtils.isBlank(model.getSubjectStart()) || StringUtils.isBlank(model.getSubjectEnd())){
return baseUtilService.setResultError("配置的规则不能为空");
}
String targetStartType = model.getSubjectStart().substring(0,1);
String targetEndType = model.getSubjectEnd().substring(0,1);
int parseIntStartParam = Integer.parseInt(model.getSubjectStart().substring(1));
int parseIntEndParam = parseIntStartParam + Integer.parseInt(model.getSubjectEnd().substring(1));
if(StringUtils.isBlank(targetStartType) || StringUtils.isBlank(targetEndType) || !targetStartType.equals(targetEndType)){
return baseUtilService.setResultError("配置规则的类型不一致");
}
Integer calendarType = null;
String formatParam = "";
if("Y".equals(targetStartType)){
//年
calendarType = Calendar.YEAR;
formatParam = "yyyy";
}else if ("M".equals(targetStartType)){
//月
calendarType = Calendar.MONTH;
formatParam = "yyyy-MM";
}else if("W".equals(targetStartType)){
//周
calendarType = Calendar.WEEK_OF_YEAR;
formatParam = "yyyy-MM-dd";
}else if ("D".equals(targetStartType)){
//日
calendarType = Calendar.DAY_OF_MONTH;
formatParam = "yyyy-MM-dd";
} else {
return baseUtilService.setResultError("当前标的类型暂不支持");
}
ComputeTime computeTime = computeTime(model.getSubjectStart(), model.getSubjectEnd(), calendarType,formatParam);
return baseUtilService.setResult(GetSetCode.HTTP_RES_CODE_200,"默认标的时段计算成功",computeTime);
}
/**
* 生成开始/结束日期
* @author yanyapan
*/
@Data
public class ComputeTime implements Serializable {
private static final long serialVersionUID = 1L;
private String startTime;
private String endTime;
}
/**
* 根据标的时段计算默认时间
* @param targetStartTime
* @param targetEndTime
* @param calendarType 日期类型
* @param formatParam 日期格式类型
* @return
*/
private ComputeTime computeTime(String targetStartTime, String targetEndTime, int calendarType,String formatParam){
ComputeTime computeTime = new ComputeTime();
//截取类型后面的参数
int targetStartParam = Integer.parseInt(targetStartTime.substring(1));
int targetEndParam = Integer.parseInt(targetEndTime.substring(1));
DateFormat format = new SimpleDateFormat(formatParam);
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(new Date());
startCalendar.add(calendarType, targetStartParam);
Date startDate = startCalendar.getTime();
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(startDate);
endCalendar.add(calendarType, targetEndParam-1);
Date endDate = endCalendar.getTime();
if(Calendar.YEAR == calendarType){
//年
computeTime.setStartTime(format.format(startDate) + "-01-01");
computeTime.setEndTime(format.format(endDate) + "-12-31");
}else if(Calendar.MONTH == calendarType){
//月
int startTimeSetYear = Integer.parseInt(format.format(startDate).substring(0, 4));
int startTimeSetMonth = Integer.parseInt(format.format(startDate).substring(5));
int endTimeSetYear = Integer.parseInt(format.format(endDate).substring(0, 4));
int endTimeSetMonth = Integer.parseInt(format.format(endDate).substring(5));
computeTime.setStartTime(format.format(startDate) + "-" + "01");
computeTime.setEndTime(format.format(endDate) + "-" + getDaysByYearMonth(endTimeSetYear,endTimeSetMonth));
}else if(Calendar.WEEK_OF_YEAR == calendarType){
//周
//查看当前日期是年份内的第几周
TargetItem targetItem = whatWeek(format.format(new Date()));
computeTime.setStartTime(getStartDayOfWeekNo(targetItem.getYear(),targetItem.getWeek() + targetStartParam));
computeTime.setEndTime(getEndDayOfWeekNo(targetItem.getYear(),targetItem.getWeek() + targetStartParam + targetEndParam - 1));
}else {
//日
computeTime.setStartTime(format.format(startDate));
computeTime.setEndTime(format.format(endDate));
}
return computeTime;
}
/**
* 当配置类型为W(周)时,获取对应的周和年份
*
*/
@Data
public class TargetItem {
private int year;
private int week;
}
private TargetItem whatWeek(String datetime) {
TargetItem targetItem = new TargetItem();
int year = Integer.parseInt(datetime.substring(0, 4));
//获取过去7天的日期
String pastDate = getPastDate(7, strToDate(datetime));
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date parsePastDate = null;
try {
parsePastDate = format.parse(pastDate);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendarPast = Calendar.getInstance();
calendarPast.setFirstDayOfWeek(Calendar.MONDAY);
calendarPast.setTime(parsePastDate);
Integer pastWeekNumbe = calendarPast.get(Calendar.WEEK_OF_YEAR);
Date currentDate = null;
try {
currentDate = format.parse(datetime);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendar = Calendar.getInstance();
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.setTime(currentDate);
Integer weekNumbe = calendar.get(Calendar.WEEK_OF_YEAR);
if(pastWeekNumbe >= 52){
targetItem.setYear(year + 1);
targetItem.setWeek(weekNumbe);
}else{
targetItem.setYear(year);
targetItem.setWeek(weekNumbe);
}
return targetItem;
}
/**
* 获取指定年份、周对应的开始日期
*/
private String getStartDayOfWeekNo(int year,int weekNo) {
Calendar cal = getCalendarFormYear(year);
cal.set(Calendar.WEEK_OF_YEAR, weekNo);
Date time = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String dateTime = format.format(time);
return dateTime;
}
/**
* 获取指定年份、周对应的结束日期
*/
private String getEndDayOfWeekNo(int year,int weekNo) {
Calendar cal = getCalendarFormYear(year);
cal.set(Calendar.WEEK_OF_YEAR, weekNo);
cal.add(Calendar.DAY_OF_WEEK, 6);
Date time = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String dateTime = format.format(time);
return dateTime;
}
/**
* 根据年 月 获取对应的月份 天数
*
*/
private int getDaysByYearMonth(int year, int month) {
Calendar a = Calendar.getInstance();
a.set(Calendar.YEAR, year);
a.set(Calendar.MONTH, month - 1);
a.set(Calendar.DATE, 1);
a.roll(Calendar.DATE, -1);
int maxDate = a.get(Calendar.DATE);
return maxDate;
}
/**
* 日期转date
* @param str
* @return
*/
private Date strToDate(String str) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
3、根据配置的日期、规则自动生成结束日期
/**
* 根据配置的日期、规则,结束日期自动生成
*
* @param dynamicDateVO
* @return
*/
public BaseResponse computeDynamicDateTime(DynamicDateVO dynamicDateVO) {
if(StringUtils.isBlank(dynamicDateVO.getDeclareStartTime())){
return baseUtilService.setResultError("配置开始日期不能为空");
}
if(StringUtils.isBlank(dynamicDateVO.getSubjectStart()) || StringUtils.isBlank(dynamicDateVO.getSubjectEnd())){
return baseUtilService.setResultError("配置规则类型不能为空");
}
String targetStartType = dynamicDateVO.getSubjectStart().substring(0,1);
String targetEndType = dynamicDateVO.getSubjectEnd().substring(0,1);
Integer calendarType = null;
if("Y".equals(targetStartType)){
//年
calendarType = Calendar.YEAR;
if(!dynamicDateVO.getDeclareStartTime().substring(5).equals("01-01")){
return baseUtilService.setResultError("当前规则时段是年,开始时间请设置为选择年份的1月1日");
}
}else if ("M".equals(targetStartType)){
//月
calendarType = Calendar.MONTH;
if(!dynamicDateVO.getDeclareStartTime().substring(8).equals("01")){
return baseUtilService.setResultError("当前配置规则时段是月,开始时间请设置为选择月份的1日");
}
}else if("W".equals(targetStartType)){
//周
calendarType = Calendar.WEEK_OF_YEAR;
}else if ("D".equals(targetStartType)){
//日
calendarType = Calendar.DAY_OF_MONTH;
} else {
return baseUtilService.setResultError("当前配置规则类型类型暂不支持");
}
DynamicDateVO dynamicDate = computeTime(dynamicDateVO.getDeclareStartTime(), dynamicDateVO.getSubjectStart(), dynamicDateVO.getSubjectEnd(), calendarType);
return baseUtilService.setResult(GetSetCode.HTTP_RES_CODE_200,"结束日期生成成功",dynamicDate);
}
/**
* 当标的时段日期发生变动时,标的结束日期自动生成
* @param chooseTime
* @param targetStartTime
* @param targetEndTime
* @param calendarType
* @return
*/
private DynamicDateVO computeTime(String chooseTime,String targetStartTime,String targetEndTime,int calendarType){
DynamicDateVO dynamicDateVO = new DynamicDateVO();
String formatParam = "";
Calendar startCalendar = Calendar.getInstance();
DateFormat format = null;
if(Calendar.YEAR == calendarType){
formatParam = "yyyy";
format = new SimpleDateFormat(formatParam);
try {
startCalendar.setTime(format.parse(chooseTime.substring(0,4)));
} catch (ParseException e) {
e.printStackTrace();
}
}else if(Calendar.MONTH == calendarType){
formatParam = "yyyy-MM";
format = new SimpleDateFormat(formatParam);
try {
startCalendar.setTime(format.parse(chooseTime));
} catch (ParseException e) {
e.printStackTrace();
}
}else if(Calendar.WEEK_OF_YEAR == calendarType){
formatParam = "yyyy-MM-dd";
format = new SimpleDateFormat(formatParam);
try {
startCalendar.setTime(format.parse(chooseTime));
} catch (ParseException e) {
e.printStackTrace();
}
}else if(Calendar.DAY_OF_MONTH == calendarType){
formatParam = "yyyy-MM-dd";
format = new SimpleDateFormat(formatParam);
try {
startCalendar.setTime(format.parse(chooseTime));
} catch (ParseException e) {
e.printStackTrace();
}
}
//截取类型后面的参数
int targetStartParam = Integer.parseInt(targetStartTime.substring(1));
int targetEndParam = Integer.parseInt(targetEndTime.substring(1));
Date startDate = startCalendar.getTime();
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(startDate);
endCalendar.add(calendarType, targetEndParam-1);
Date endDate = endCalendar.getTime();
if(calendarType == Calendar.YEAR){
dynamicDateVO.setDeclareStartTime(chooseTime);
dynamicDateVO.setDeclareEndTime(format.format(endDate) + "-12-31");
}
if(calendarType == Calendar.MONTH){
int endTimeSetYear = Integer.parseInt(format.format(endDate).substring(0, 4));
int endTimeSetMonth = Integer.parseInt(format.format(endDate).substring(5));
dynamicDateVO.setDeclareStartTime(chooseTime);
dynamicDateVO.setDeclareEndTime(format.format(endDate) + "-" + getDaysByYearMonth(endTimeSetYear,endTimeSetMonth));
}
if(calendarType == Calendar.WEEK_OF_YEAR){
TargetItem targetItem = whatWeek(chooseTime);
dynamicDateVO.setDeclareStartTime(chooseTime);
dynamicDateVO.setDeclareEndTime(getEndDayOfWeekNo(targetItem.getYear(),targetItem.getWeek() + targetEndParam - 1));
}
if(calendarType == Calendar.DAY_OF_MONTH){
dynamicDateVO.setDeclareStartTime(chooseTime);
dynamicDateVO.setDeclareEndTime(format.format(endDate));
}
return dynamicDateVO;
}
/**
* 当标的开始日期发生变化时,标的结束日期自动变化
*/
@Data
public class DynamicDateVO implements Serializable {
/**
* 配置开始时间
*/
private String declareStartTime;
/**
* 配置结束时间
*/
private String declareEndTime;
/**
* 配置类型规则
*/
private String subjectStart;
/**
* 配置类型规则
*/
private String subjectEnd;
}
4、总结
- 该日期配置规则工具类使用Calendar封装,在开发中也学习参考了corn日期表达式。
- 对开发工具API的使用熟练程度,对解决问题来说有一定的影响。深入理解,对遇到问题设计解决方案时有事半功倍的作用。