package com.zhou.util;
import com.zhou.common.enums.RateTypeEnum;
import com.zhou.util.enums.IEnum;
import lombok.Data;
import lombok.SneakyThrows;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 通用自然日转换器
* @author lang.zhou
* @since 2024/3/12 9:53
*/
@Data
public class DateParse {
/**
* 默认输出格式,默认yyyyMMdd
*/
//private static final SimpleDateFormat DF = new SimpleDateFormat("yyyyMMdd");
/**
* 自定义输出格式,默认yyyyMMdd
*/
private String pattern ;
private SimpleDateFormat format ;
private static DateParse PARSER = new DateParse("yyyyMMdd");
private DateParse(String pattern) {
this.pattern = pattern;
this.format = new SimpleDateFormat(pattern);
}
/**
* 传入一个日期格式,返回转换器
* @param pattern yyyyMMdd
*/
public static DateParse ct(String pattern){
return new DateParse(pattern);
}
/**
* 返回默认转换器yyyyMMdd
*/
public static DateParse ct(){
return PARSER;
}
public static void main(String[] args){
System.out.println(DateParse.ct("yyyy-MM-dd").getNextDay(20240309,-4));
System.out.println(DateParse.ct("yyyy-MM-dd").getLastDayOfWeek(20240312,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getFirstDayOfWeek(20240312,1));
System.out.println(DateParse.ct("yyyy-MM-dd").getFirstDayOfMonth(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getLastDayOfMonth(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getFirstDayOfQuarter(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getLastDayOfQuarter(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getFirstDayOfYear(20240309,1));
System.out.println(DateParse.ct("yyyy-MM-dd").getLastDayOfYear(20240309,1));
System.out.println(DateParse.ct("yyyy-MM-dd").getFirstDayOfHalfYear(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getLastDayOfHalfYear(20240309,-1));
System.out.println(DateParse.ct("yyyy-MM-dd").getDayInMonth(20240312,1));
System.out.println(DateParse.ct("yyyy-MM-dd").getDayInWeek(20240312,1));
System.out.println(DateParse.ct("yyyy-MM-dd").getDayInQuarter(20240312,60));
System.out.println(DateParse.ct("yyyy-MM-dd").getDayInYear(20240312,60));
System.out.println(DateParse.getBetweenDay(20240309,20240318));
System.out.println(DateParse.getBetweenWeek(20240311,20240317));
System.out.println(DateParse.getBetweenMonth(20240331,20240401));
System.out.println(DateParse.getBetweenQuarter(20240331,20240401));
System.out.println(DateParse.getBetweenYear(20240331,20260401));
System.out.println(DateParse.getWeekInYear(20240312));
System.out.println(DateParse.getDayInWeek(20240312));
System.out.println(DateParse.getMonthInYear(20240312));
System.out.println(DateParse.getQuarterInYear(20240312));
System.out.println(DateParse.getYear(20240312));
System.out.println(DateParse.getWeekInYear(20241230));
}
/**
* 将字符型或Date对象转换成整型,yyyyMMdd格式
* @return yyyyMMdd
*/
@SneakyThrows
public static Integer parseInt(Object date){
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
if(date instanceof Long){
return Integer.parseInt(df.format(new Date((Long) date)));
}else if(date instanceof Number){
return ((Number) date).intValue();
}else if(date instanceof String){
return Integer.parseInt(replace(date.toString(),df));
}else if(date instanceof Date){
return Integer.parseInt(df.format((Date) date));
}
throw new IllegalArgumentException(date.toString() + "无法转换为日期格式");
}
/**
* 将字符型或Date对象转换成字符,yyyyMMdd格式
* @return yyyyMMdd
*/
@SneakyThrows
public static String parseYmd(Object date){
return parseInt(date).toString();
}
/**
* 将字符型或Date对象转换成format格式的字符串
*/
@SneakyThrows
public String parseString(Object date){
return format.format(parseDate(date));
}
/**
* 去除输入字符对象中的特殊字符,只保留ymd
*/
private static String replace(String o, SimpleDateFormat df){
//只保留数字
String s = StringTool.filterNum(o);
//支持6位日期
if(s.length() == 6){
s = s.substring(0,4) + "0" + s.charAt(4) + "0" + s.charAt(5);
}
if(s.length() > 8){
try{
long v = Long.parseLong(s);
s = df.format(new Date(v));
}catch (Exception e){
throw new IllegalArgumentException(s + "无法转换为日期格式");
}
}
return s;
}
/**
* 将任意对象转为Date对象
*/
@SneakyThrows
public static Date parseDate(Object date){
return parseDate(date,new SimpleDateFormat("yyyyMMdd"));
}
@SneakyThrows
public static Date parseDate(Object date, SimpleDateFormat df){
if(date instanceof Long){
return new Date((Long) date);
}else if(date instanceof Number){
return df.parse(replace(date.toString(),df));
}else if(date instanceof String){
return df.parse(replace(date.toString(),df));
}else if(date instanceof Date){
return (Date) date;
}
throw new IllegalArgumentException(date + "无法转换为日期格式");
}
public static Calendar getCalendar(Object dateObj){
Calendar calendar = Calendar.getInstance();
Date date = parseDate(dateObj);
calendar.setTime(date);
return calendar;
}
/**
* 获取后n天,n为负数时表示前n天,n为0表示当天
* @param dateObj:可以输入整型、字符串或Date对象。格式为20180926 或"2018-09-26" 或"2018/09/26"
*/
public String getNextDay(Object dateObj, int n){
Calendar calendar = getCalendar(dateObj);
calendar.add(Calendar.DATE, n);
return format.format(calendar.getTime());
}
/**
* 获取date所在周的后n周最后一天,n为负数时表示前n周,n为0表示本周
* @param dateObj:格式为20180926
*/
public String getLastDayOfWeek(Object dateObj, int n) {
Calendar calendar = getCalendar(dateObj);
calendar.setFirstDayOfWeek(Calendar.MONDAY);//将每周第一天设为星期一,默认是星期天
calendar.add(Calendar.DATE, 7*n);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
return format.format(calendar.getTime());
}
/**
* 获取date所在周的后n周第一天,n为负数时表示前n周,n为0表示本周
* @param dateObj:格式为20180926
*/
public String getFirstDayOfWeek(Object dateObj,int n) {
Calendar calendar = getCalendar(dateObj);
calendar.setFirstDayOfWeek(Calendar.MONDAY);//将每周第一天设为星期一,默认是星期天
calendar.add(Calendar.DATE, 7*n);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
return format.format(calendar.getTime());
}
/**
* 获取date所在月的第后n个月的最后一天,n为负数时表示前n个月,n为0表示本月
*/
public String getLastDayOfMonth(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
calendar.add(Calendar.MONTH, n+1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.DATE, -1);
return format.format(calendar.getTime());
}
/**
* 获取date所在月的第后n个月的第一天,n为负数时表示前n个月,n为0表示本月
*/
public String getFirstDayOfMonth(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
calendar.add(Calendar.MONTH, n);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return format.format(calendar.getTime());
}
/**
* 获取date所在季度的后n个季度的最后一天,n为负数时表示前n个季度,n为0表示本季度
* @param dateObj:格式为20180926
*/
// public String getLastDayOfQuarter(Object dateObj, int n){
// Calendar c = getCalendar(dateObj);
// int date = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(c.getTime()));
// int monthSet = date%10000/100-1;
// int month = monthSet+1;
// c.add(Calendar.MONTH,n*3+1);
// c.set(Calendar.DAY_OF_MONTH, 1);
// c.add(Calendar.DATE, -1);
// c.add(Calendar.MONTH, 3-(month%3==0 ? 3 : month%3));
// return format.format(c.getTime());
// }
public String getLastDayOfQuarter(Object dateObj, int n) {
Calendar c = getCalendar(dateObj);
// 先移动到当前季度的第一个月
int currentMonth = c.get(Calendar.MONTH);
int quarterStartMonth = (currentMonth / 3) * 3;
c.set(Calendar.MONTH, quarterStartMonth);
c.set(Calendar.DAY_OF_MONTH, 1);
// 添加n个季度的偏移
c.add(Calendar.MONTH, n * 3);
// 移动到季度的最后一天
c.add(Calendar.MONTH, 3); // 下个季度的第一个月
c.add(Calendar.DAY_OF_MONTH, -1); // 前一天的当前季度的最后一天
return format.format(c.getTime());
}
/**
* 获取date所在季度的后n个季度的第一天,n为负数时表示前n个季度,n为0表示本季度
* @param dateObj:格式为20180926
*/
public String getFirstDayOfQuarter(Object dateObj,int n){
Calendar c = getCalendar(dateObj);
int date = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(c.getTime()));
int monthSet = date%10000/100-1;
int month = monthSet+1;
c.add(Calendar.MONTH,n*3);
c.set(Calendar.DAY_OF_MONTH, 1);
c.add(Calendar.MONTH, 1-(month%3==0 ? 3 : month%3));
return format.format(c.getTime());
}
/**
* 获取date所在年的后n年的最后一天,n为负数时表示前n年,n为0表示本年
* @param dateObj:格式为20180926
*/
public String getLastDayOfYear(Object dateObj, int n){
Calendar calendar = getCalendar(dateObj);
calendar.add(Calendar.YEAR, n+1);
calendar.set(Calendar.DAY_OF_YEAR, 1);
calendar.add(Calendar.DATE, -1);
return format.format(calendar.getTime());
}
public static int getDayOfYear(Object dateObj){
Calendar calendar = getCalendar(dateObj);
return calendar.get(Calendar.YEAR);
}
/**
* 获取date所在年的后n年的第一天,n为负数时表示前n年,n为0表示本年
* @param dateObj:格式为20180926
*/
public String getFirstDayOfYear(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
calendar.add(Calendar.YEAR, n);
calendar.set(Calendar.DAY_OF_YEAR, 1);
return format.format(calendar.getTime());
}
/**
* 获取date所在半年的后n个半年的第一天,n为负数时表示前n个半年,n为0表示本半年
* @param dateObj:格式为20180926
*/
public String getFirstDayOfHalfYear(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
int addM = n * 6;
calendar.add(Calendar.MONTH, addM);
int m = calendar.get(Calendar.MONTH) + 1;
calendar.set(Calendar.MONTH,m > 6 ? 6 : 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return format.format(calendar.getTime());
}
/**
* 获取date所在半年的后n个半年的最后一天,n为负数时表示前n个半年,n为0表示本半年
* @param dateObj:格式为20180926
*/
public String getLastDayOfHalfYear(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
int addM = n * 6;
calendar.add(Calendar.MONTH, addM);
int m = calendar.get(Calendar.MONTH) + 1;
calendar.set(Calendar.MONTH,m > 6 ? 11 : 5);
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.DATE, -1);
return format.format(calendar.getTime());
}
/**
* 获取两个日期间的天数
*/
public static int getBetweenDay(Object d1,Object d2){
long a= getCalendar(d1).getTimeInMillis();
long b= getCalendar(d2).getTimeInMillis();
double betweenDays = (((b - a) * 1.0) / (1000 * 60 * 60 * 24)) + 0.5;
return (int) Math.floor(betweenDays);
}
/**
* 获取两个日期所间隔的周数
*/
private static int getBetweenWeek(Object date1,Object date2){
int d1 = Integer.parseInt(PARSER.getFirstDayOfWeek(date1,0));
int d2 = Integer.parseInt(PARSER.getFirstDayOfWeek(date2,0));
long n = getBetweenDay(d1,d2);
return (int)(n/7);
}
/**
* 获取两个日期所在月数的差值
*/
public static int getBetweenMonth(Object d1,Object d2){
int date1 = parseInt(d1);
int date2 = parseInt(d2);
int year1 = date1/10000;
int year2 = date2/10000;
int month1 = date1%10000/100;
int month2 = date2%10000/100;
if(month2 < month1){
month2 += 12;
year2 --;
}
return (year2-year1)*12+month2-month1;
}
/**
* 获取两个日期所在季度数的差值
*/
public static int getBetweenQuarter(Object date1,Object date2){
return getBetweenMonth(PARSER.getFirstDayOfQuarter(date1,0),PARSER.getFirstDayOfQuarter(date2,0))/3;
}
/**
* 获取两个日期所在年数的差值
*/
public static int getBetweenYear(Object date1,Object date2){
return parseInt(date2)/10000 - parseInt(date1)/10000;
}
/**
* 获取date在本年的周数
*/
public static int getWeekInYear(Object dateObj){
Calendar calendar = getCalendar(dateObj);
//calendar.setMinimalDaysInFirstWeek(7);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
/**
* 获取date在本月的周数
*/
public static int getWeekInMonth(Object dateObj){
Calendar calendar = getCalendar(dateObj);
//calendar.setMinimalDaysInFirstWeek(7);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
return calendar.get(Calendar.WEEK_OF_MONTH);
}
/**
* 获取date是本星期中的第几天
* @return 返回1~7
*/
public static int getDayInWeek(Object dateObj){
Calendar calendar = getCalendar(dateObj);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
int dayOfWeek=calendar.get(Calendar.DAY_OF_WEEK);
return dayOfWeek!=1 ? dayOfWeek-1 : 7;
}
/**
* 获取dateObj是所在月的第几天
*/
public static int getDayInMonth(Object dateObj){
Calendar calendar = getCalendar(dateObj);
return calendar.get(Calendar.DAY_OF_MONTH);
}
/**
* 获取dateObj所在月的第n天,若超出本月天数,返回本月最后一天
*/
public String getDayInMonth(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
n = n > 0 ? n :32;
if(n > calendar.getActualMaximum(Calendar.DAY_OF_MONTH)){
return getLastDayOfMonth(dateObj,0);
}
return getNextDay(getFirstDayOfMonth(dateObj,0),n - 1);
}
/**
* 获取dateObj所在年
*/
public static int getYear(Object dateObj){
int date = parseInt(dateObj);
return date/10000;
}
/**
* 获取dateObj所在月是本年的第几个月
*/
public static int getMonthInYear(Object dateObj){
int date = parseInt(dateObj);
return date%10000/100;
}
/**
* 获取dateObj是上半年还是下半年
*/
public static String getHalfYear(Object dateObj){
int month = getMonthInYear(dateObj);
return month > 6 ? "下半年" : "上半年";
}
/**
* 获取dateObj所在周的第n天,若超出本周天数,返回本周最后一天
*/
public String getDayInWeek(Object dateObj,int n){
Calendar calendar = getCalendar(dateObj);
n = n > 0 ? n :32;
if(n>calendar.getActualMaximum(Calendar.DAY_OF_WEEK)){
return getLastDayOfWeek(dateObj,0);
}
return getNextDay(getFirstDayOfWeek(dateObj,0),n - 1);
}
public static String getWeek(Date date) {
return "周" + "?一二三四五六日".charAt(getDayInWeek(date));
}
/**
* 获取dateObj所在季度的第n天,若超出本季度天数,返回本季度最后一天
*/
public String getDayInQuarter(Object dateObj, int n){
String fir = PARSER.getFirstDayOfQuarter(dateObj,0);
String las = PARSER.getLastDayOfQuarter(dateObj,0);
String now = PARSER.getNextDay(fir,n - 1);
int d = parseInt(now);
if(d > parseInt(las)){
return getLastDayOfQuarter(dateObj,0);
}
return getNextDay(fir,n - 1);
}
/**
* 获取dateObj所在年的第n天,若超出本年天数,返回本年最后一天
*/
public String getDayInYear(Object dateObj, int n){
Calendar calendar = getCalendar(dateObj);
n = n > 0 ? n :32;
if(n > calendar.getActualMaximum(Calendar.DAY_OF_YEAR)){
return getLastDayOfYear(dateObj,0);
}
return getNextDay(getFirstDayOfYear(dateObj,0),n - 1);
}
public static int getQuarterInYear(Object dateObj){
int month = parseInt(dateObj)%10000/100;
if(month>=1 && month<=3){
return 1;
}else if(month>3 && month<=6){
return 2;
}else if(month>6 && month<=9){
return 3;
}else if(month>9 && month<=12){
return 4;
}
return 0;
}
/**
* 拿到一年内的日期
* @param date 一年内的任意日期
*/
public static List<Integer> getYearDays(Object date){
int startDay = Integer.parseInt(DateParse.ct().getFirstDayOfYear(date,0));
int endDay = Integer.parseInt(DateParse.ct().getLastDayOfYear(date,0));
List<Integer> res = new ArrayList<>();
int i = 0;
while (true){
int nextDay = Integer.parseInt(DateParse.ct().getNextDay(startDay, i));
if(nextDay > endDay){
break;
}else{
res.add(nextDay);
}
i ++;
}
return res;
}
}
06-30
4055
