昨天有朋友有这个这样的需求,就是月的划分,是他给定的一个日期,譬如每月的21号为一个分段点,意思是 2013-06-21 到 2013-07-20 为一时间段,2013-07-21 到 2013-08-20 为另一段。那么需要用这个规则去分割他给出的时间段(譬如拆分 2012-01-01 到2013-01-01)
写了个逻辑,反反复复,弄了大半天,记下源码,以备不时之需。
package com.jy.action.bases;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Map.Entry;
public class SplitDateTest2 {
private final static int SPLIT_DAY = 21;//要切割的时间点,或者叫分段点
/**
* @deprecated 分段逻辑是:单独处理段头和段位,中间工整的段就是循环处理。
* @param startDate 时间段的开始时间
* @param endDate 时间段的结束时间
*/
public TreeMap<Date, Date> splidDate(Date startDate, Date endDate){
TreeMap<Date, Date> dateMap = new TreeMap<Date, Date>();
//判断 startDate 是否大于 endDate,如果大于就 不作处理。
if(startDate.compareTo(endDate) > 0){
//此处应该改为 log输出信息
//System.out.println("startDate("+startDate.toLocaleString()+") 需要小于 endDate("+endDate.toLocaleString()+")");
return dateMap;
}
//计算 startDate 与 endDate 相差多少个月
int mBetween = (endDate.getYear() - startDate.getYear())*12 + endDate.getMonth() - startDate.getMonth();
//根据startDate和分段点生成分段时间
Calendar splitDate = Calendar.getInstance();
splitDate.setTime(startDate);
splitDate.set(Calendar.DATE, SPLIT_DAY);
//根据startDate和分段点生成分段时间的最后一天的时间。
Calendar splitDateEnd = Calendar.getInstance();
splitDateEnd.setTime(startDate);
splitDateEnd.set(Calendar.DATE, SPLIT_DAY - 1);
// 不需要分段start>>>>>>>>>>>>>>
if (mBetween == 0 && (startDate.getDate() >= SPLIT_DAY || endDate.getDate() < SPLIT_DAY)){
dateMap.put(startDate, endDate);
return dateMap;
}
// 不需要分段end<<<<<<<<<<<<<<<<
//需要分段start>>>>>>>>>>>>>>>>>
//首段前处理start
if (startDate.getDate() < SPLIT_DAY){
dateMap.put(startDate, splitDateEnd.getTime());
splitDateEnd.set(Calendar.MONTH, splitDateEnd.get(Calendar.MONTH) + 1);
}else{
splitDateEnd.set(Calendar.MONTH, splitDateEnd.get(Calendar.MONTH) + 1);
dateMap.put(startDate, splitDateEnd.getTime());
}
//首段前处理end
//分段s前处理start>>>>>>>>>
//计算 固定的分段, 给后面的固定分段循环用
//固定的要分的段 例如 2013-06-xx到 2013-09-xx mBetween=3
//所以一定会有mBetween-2=1个固定的或标准的分段,也就是 2013-07-xx到 2013-08-xx
mBetween = mBetween - 2;
//如果是起始日期在 SPLIT_DAY 前,则固定分段 循环次数+1
if (startDate.getDate() < SPLIT_DAY)
mBetween ++;
//如果是终止日期在 SPLIT_DAY 前,则固定分段 循环次数+1
if (endDate.getDate() >= SPLIT_DAY)
mBetween ++;
//分段s前处理end<<<<<<<<<<<
if (startDate.getDate() < SPLIT_DAY){
for (int i=1; i<=mBetween; i++){
dateMap.put(splitDate.getTime(), splitDateEnd.getTime());
splitDate.set(Calendar.MONTH, splitDate.get(Calendar.MONTH) + 1);
splitDateEnd.set(Calendar.MONTH, splitDateEnd.get(Calendar.MONTH) + 1);
}
}else{
for (int i=1; i<=mBetween; i++){
splitDate.set(Calendar.MONTH, splitDate.get(Calendar.MONTH) + 1);
splitDateEnd.set(Calendar.MONTH, splitDateEnd.get(Calendar.MONTH) + 1);
dateMap.put(splitDate.getTime(), splitDateEnd.getTime());
}
splitDate.set(Calendar.MONTH, splitDate.get(Calendar.MONTH) + 1);//这属于末段处理逻辑
}
dateMap.put(splitDate.getTime(), endDate);//这属于末段处理
//需要分段end<<<<<<<<<<<<<<
return dateMap;
}
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
//测试1
// Date startDate = sdf.parse("2013-02-12");
// Date endDate = sdf.parse("2013-08-13");
//测试2
// Date startDate = sdf.parse("2013-02-12");
// Date endDate = sdf.parse("2013-08-23");
//测试3
// Date startDate = sdf.parse("2013-02-22");
// Date endDate = sdf.parse("2013-08-13");
//测试4
// Date startDate = sdf.parse("2013-02-22");
// Date endDate = sdf.parse("2013-08-23");
//测试5
Date startDate = sdf.parse("2013-01-12");
Date endDate = sdf.parse("2013-06-23");
SplitDateTest2 sdt = new SplitDateTest2();
TreeMap<Date, Date> dateMap = sdt.splidDate(startDate, endDate);
Iterator<Entry<Date, Date>> it = dateMap.entrySet().iterator();
Entry<Date, Date> entry;
while(it.hasNext()){
entry = it.next();
System.out.println(entry.getKey().toLocaleString()+"到"+entry.getValue().toLocaleString());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}