昨天有朋友有這個這樣的需求,就是月的劃分,是他給定的一個日期,譬如每月的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();
}
}
}