在实际开发中,经常出现有统计的需求,按年、季度、月、周、日统计,给定一个时间,获取该时间的年度、季度、月度、周、当天的时间范围
Date 类型
/*
* parem 统计周期 year quarter month week
* obeginTime 给定时间
* _beginTime 返回的Date类型周期开始时间
* _endTime 返回的Date类型周期结束时间
* 返回 00:00:00~00:00:00 语句中的sql条件应为 #{_beginTime}<=time<#{_endTime}
*/
public static Map<String, Date> setTimeChange(String parem, Date obeginTime, Date _beginTime, Date _endTime) {
Date time = new Date();
if (obeginTime != null) {
time = obeginTime;
}
if ("year".equals(parem)) {
_beginTime = DateUtils.getFormatDay(DateUtils.getFormatDayStr(time, DateUtils.DATE_FORMAT_yyyy) + "-01-01 00:00:00", DateUtils.DATE_FORMAT_yyyy_MM_HH_mm_ss);
_endTime = DateUtils.getYearAfter(_beginTime, 1);
} else if ("quarter".equals(parem)) {
//本季度初
_beginTime = DateUtils.getCurrentQuarterStartTime(time);
_endTime = DateUtils.getMonthAfter(_beginTime, 3); //下个季度初
} else if ("month".equals(parem)) {
_beginTime = DateUtils.getFormatDay(DateUtils.getFormatDayStr(time, DateUtils.DATE_FORMAT_yyyy_MM) + "-01 00:00:00", DateUtils.DATE_FORMAT_yyyy_MM_HH_mm_ss);
_endTime = DateUtils.getMonthAfter(_beginTime, 1);
} else if ("week".equals(parem)) {
LocalDate localDate = time.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
// 设置一周中的开始时间为周一 不然默认是周日开始周六结束
LocalDate currentMonday = localDate.with(DayOfWeek.MONDAY);
LocalDate nextMonday = currentMonday.plusWeeks(1);
Date[] dates = new Date[2];
dates[0] = Date.from(currentMonday.atStartOfDay(ZoneId.systemDefault()).toInstant());
dates[1] = Date.from(nextMonday.atStartOfDay(ZoneId.systemDefault()).toInstant());
_beginTime = dates[0];
_endTime = dates[1];
} else {
_beginTime = DateUtils.getFormatDay(DateUtils.getFormatDayStr(time, DateUtils.DATE_FORMAT_yyyy_MM_dd) + " 00:00:00", DateUtils.DATE_FORMAT_yyyy_MM_HH_mm_ss);
_endTime = DateUtils.getDayAfter(_beginTime, 1);
}
Map<String, Date> changeAfterDate = new HashMap<>();
changeAfterDate.put("beginTime", _beginTime);
changeAfterDate.put("endTime", _endTime);
return changeAfterDate;
}
DateTime类型
private Map<String, DateTime> SetTimeChange(String parem, DateTime obeginTime, DateTime _beginTimeRef, DateTime _endTimeRef) {
Map<String, DateTime> result = new HashMap<>();
String tmFom = "yyyy-MM-dd HH:mm:ss";
DateTime time = DateTime.now();
if (obeginTime != null) {
time = obeginTime;
}
if (parem.equals("year")) {
LocalDateTime localDateTime = time.toJdkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime startOfYear = localDateTime.with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
_beginTimeRef = DateUtil.date(startOfYear);
_endTimeRef = _beginTimeRef.offsetNew(DateField.YEAR,1);
} else if (parem.equals("quarter")) {
// getField 0-11 表示1-12月
int addMonths = 0 - (time.getField(DateField.MONTH)) % 3;
int addDays = 1 - time.getField(DateField.DAY_OF_MONTH);
_beginTimeRef = time.offsetNew(DateField.MONTH, addMonths).offsetNew(DateField.DAY_OF_MONTH,addDays); //本季度初
LocalDateTime localDateTime = _beginTimeRef.toJdkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime startOfQuarter = localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
_beginTimeRef = DateUtil.date(startOfQuarter);
_endTimeRef = _beginTimeRef.offsetNew(DateField.MONTH,3); //下个季度初
} else if (parem.equals("month")) {
LocalDateTime localDateTime = time.toJdkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime startOfMonth = localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
_beginTimeRef = DateUtil.date(startOfMonth);
_endTimeRef = _beginTimeRef.offset(DateField.MONTH,1);
} else if (parem.equals("week")) {
int weeknow = time.getField(DateField.DAY_OF_WEEK) - 1;//获得指定日期是星期几,最终结果 0周日 1周一 2周二
weeknow = (weeknow == 0 ? 7 : weeknow);
//本周一
_beginTimeRef = DateTime.of(time.offsetNew(DateField.DAY_OF_WEEK,(1-weeknow)).toString("yyyy-MM-dd 00:00:00"),tmFom);
//本周最后一天
LocalDateTime localDateTime = _beginTimeRef.toJdkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime endOfWeek = localDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
_endTimeRef = DateUtil.date(endOfWeek).offsetNew(DateField.DAY_OF_MONTH,7);
} else {
LocalDateTime localDateTime = time.toJdkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime startOfDay = localDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
_beginTimeRef = DateUtil.date(startOfDay);
DateTime dateTime = _beginTimeRef;
_endTimeRef = dateTime.offsetNew(DateField.DAY_OF_MONTH, 1);
}
result.put("beginTime", _beginTimeRef);
result.put("endTime", _endTimeRef);
return result;
}
关于使用DateTime的时间偏移方法需要注意 offset offsetNew 的使用
DateTime dateTime1 = DateTime.now();
DateTime dateTime2 = dateTime1.offset(DateField.DAY_OF_MONTH,1);
这样会导致 dateTime1和dateTime2的值一样
如果期望dateTime2在dateTime1的基础上偏移,而不改变dateTime1的值,可以使用offsetNew
如果使用Calendar类需要注意,这个类的周期开始日期跟我们日常使用的是不一致的,需要我们手动设置基准日,没有设置的时候如下,
public class test {
public static void main(String[] args) {
Date time = new Date(1710139146000L);
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
int lastDayOfWeek = calendar.get(Calendar.DAY_OF_MONTH);
}
}
输入的时间戳是2024-03-09,获取本周的第一天,返回的是3号
输入的时间戳是2024-03-04,获取本周的第一天,返回的是3号
输入的时间戳是2024-03-10,获取本周的第一天,返回的是10号
输入的时间戳是2024-03-11,获取本周的第一天,返回的是10号
由此可得 没有设置基准值的情况,默认是周日【上周】为本周的第一天,周六为最后一天
设置好基准日如下
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
// 找到本周的周一
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
if (calendar.getTime().after(time)) {
calendar.add(Calendar.DAY_OF_WEEK, -7);
}
Date weekStart = calendar.getTime();
System.out.println("本周周一的日期为:" + weekStart);
// 找到本周的周日
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
if (calendar.getTime().before(time)) {
calendar.add(Calendar.DAY_OF_WEEK, 7);
}
Date weekEnd = calendar.getTime();
System.out.println("本周周日的日期为:" + weekEnd);
根据实际需要设置sql的开闭区间