集智数据平台根据输入日期解决当月工作日和剩余工作日的自定义函数

第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-1date_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;

}

}