根据输入日期解决当月工作日和剩余工作日的自定义函数
第46章 根据输入日期解决当月工作日和剩余工作日的自定义函数
1. 问题概述
报表参数模板在第一次加载进来,需要根据当前的查询日期首先定位到属于当前月份的第几个工作日,当前月总共有多少个工作日,以及还剩下多个个工作日,如图:当前输入日期是2010-01-08, 当月总共20工作日,当前是第5工作日,剩余15工作日
此工作日的计算只是报表右上角的一部分,整个报表预览图如:
2. 算法及调用规则
A. 解决思路:
1.对于任意2个日期比如:date_start=2006-10-1、date_end=2006-10-14,首先计算这连个日期之间的时间间隔(天数),然后分别对date_start 和date_end 取得它们下一个星期一的日期.这样就可以得到一个新的可以整除7的完整日期间隔(这个新的日期间隔已经把星期几的问题剔出掉了).
2.换一种说法就是我们可以得到,这两个新的日期之间的周数,拿这个周数乘以5就是工作日期了(tmpWorkingDays),但是这个日期并不是我们所要的日期,接下来我们要做的就是计算date_start,date_end这两个日期对于根据它们所产生的新的日期之间的时间偏移量. date_start的偏移量(date_start_change)是需要加的,而date_end的这个偏移量(date_end_change)是需要减去的.
3.最后我们只要用tmpWorkingDays+date_start_change-date_end_change就是我们所要求的实际工作日了,以下是所有实现代码(两个日期跨年也没有问题)
B:报表参数模板上的用法:
C:自定义函数的登记:
3. 程序说明
调用格式:CalWorkDate(起始参数,结束参数);
例:=CalWorkDate(monthbegin(@arg1),monthend(@arg1))
package expression;
import java.util.Calendar;
import java.util.Date;
import com.runqian.base4.util.ReportError;
import com.runqian.report4.model.expression.Expression;
import com.runqian.report4.model.expression.Function;
import com.runqian.report4.model.expression.Variant2;
import com.runqian.report4.usermodel.Context;
public class CalWorkDate extends Function {
/**
* 主要思路: 对于任意2个日期比如:date_start=2006-10-1、date_end=2006-10-14 ,
* 首先计算这连个日期之间的时间间隔(天数),然后分别对date_start 和date_end 取得它们下一个星期一的日期,
* 这样就可以得到一个新的可以整除7的完整日期间隔(这个新的日期间隔已经把星期几的问题剔出掉了),
* 换一种说法就是我们可以得到,这两个新的日期之间的周数,拿这个周数乘以5就是工作日期了(tmpWorkingDays)。
* 但是这个日期并不是我们所要的日期,接下来我们要做的就是计算date_start,date_end这两个日期对于根据它们所产生的新的日期之间的时间偏移量,
* date_start的偏移量(date_start_change)是需要加的,而date_end的这个偏移量(date_end_change)是需要减去的。
* 最后我们只要用tmpWorkingDays+date_start_change-date_end_change就是我们所要求的实际工作日了。
* 以下是所有实现代码(两个日期跨年也没有问题)
*/
public Object calculate(Context ctx, boolean inputValue) {
if (this.paramList.size() == 0)
throw new ReportError(“该函数需要两个日期参数!“);
// 取得计算表达式
Expression exp1 = (Expression) this.paramList.get(0);
if (exp1 == null)
throw new ReportError(“包含有无效参数!“);
Object obj1 = Variant2.getValue(exp1.calculate(ctx, inputValue), false,
false);
Expression exp2 = (Expression) this.paramList.get(1);
if (exp2 == null)
throw new ReportError(“包含有无效参数!“);
Object obj2 = Variant2.getValue(exp2.calculate(ctx, inputValue), false,
false);
Date d1 = (Date) obj1;
Date d2 = (Date) obj2;
Calendar cal1 = Calendar.getInstance();
cal1.setTime(d1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(d2);
return new CalWorkDate().getWorkingDay(cal1,cal2);
}
public int getDaysBetween(java.util.Calendar d1, java.util.Calendar d2) {
if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
java.util.Calendar swap = d1;
d1 = d2;
d2 = swap;
}
int days = d2.get(java.util.Calendar.DAY_OF_YEAR)
- d1.get(java.util.Calendar.DAY_OF_YEAR);
System.out.println(“d2:”+d2.get(java.util.Calendar.DAY_OF_YEAR));
System.out.println(“days:”+days);
int y2 = d2.get(java.util.Calendar.YEAR);
if (d1.get(java.util.Calendar.YEAR) != y2) {
d1 = (java.util.Calendar) d1.clone();
do {
days += d1.getActualMaximum(java.util.Calendar.DAY_OF_YEAR);
d1.add(java.util.Calendar.YEAR, 1);
} while (d1.get(java.util.Calendar.YEAR) != y2);
}
return days;
}
/**
* 计算2个日期之间的相隔天数
*
* @param d1
* @param d2
* @return
*/
public int getWorkingDay(java.util.Calendar d1, java.util.Calendar d2) {
int result = -1;
if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
java.util.Calendar swap = d1;
d1 = d2;
d2 = swap;
}
int charge_start_date = 0;// 开始日期的日期偏移量
int charge_end_date = 0;// 结束日期的日期偏移量
// 日期不在同一个日期内
int stmp;
int etmp;
stmp = 7 – d1.get(Calendar.DAY_OF_WEEK);
etmp = 7 – d2.get(Calendar.DAY_OF_WEEK);
System.out.println(“stmp:”+stmp);
System.out.println(“etmp:”+etmp);
if (stmp != 0 && stmp != 6) {// 开始日期为星期六和星期日时偏移量为0
charge_start_date = stmp – 1;
}
if (etmp != 0 && etmp != 6) {// 结束日期为星期六和星期日时偏移量为0
charge_end_date = etmp – 1;
}
//
result = (getDaysBetween(this.getNextMonday(d1), this.getNextMonday(d2)) / 7)
* 5 + charge_start_date – charge_end_date;
System.out.println(“1:”+(getDaysBetween(this.getNextMonday(d1), this.getNextMonday(d2)) / 7)
* 5 );
System.out.println(“2:”+charge_start_date);
System.out.println(“3:”+charge_end_date);
return result;
}
/**
* 获得日期的下一个星期一的日期
*
* @param date
* @return
*/
public Calendar getNextMonday(Calendar date) {
Calendar result = null;
result = date;
do {
result = (Calendar) result.clone();
result.add(Calendar.DATE, 1);
} while (result.get(Calendar.DAY_OF_WEEK) != 2);
return result;
}
}