/**
* Implements the CFML Function datediff
*/
package railo.runtime.functions.dateTime;
import java.util.Calendar;
import java.util.TimeZone;
import railo.commons.date.JREDateTimeUtil;
import railo.runtime.PageContext;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.FunctionException;
import railo.runtime.ext.function.Function;
import railo.runtime.op.Decision;
import railo.runtime.type.dt.DateTime;
/**
*
*/
public final class DateDiff implements Function {
//private static final int DATEPART_S = 0;
//private static final int DATEPART_N = 1;
//private static final int DATEPART_H = 2;
private static final int DATEPART_D = 3;
private static final int DATEPART_Y = DATEPART_D;
private static final int DATEPART_YYYY = 10;
private static final int DATEPART_M = 11;
private static final int DATEPART_W = 12;
private static final int DATEPART_WW = DATEPART_W;
private static final int DATEPART_Q = 20;
//private static Calendar _cRight;
//private static Calendar _cLeft;
/**
* @param pc
* @param s
* @param date
* @param date1
* @return
* @throws ExpressionException
*/
public synchronized static double call(PageContext pc , String datePart, DateTime left, DateTime right) throws ExpressionException {
long msLeft = left.getTime();
long msRight = right.getTime();
TimeZone tz = pc.getTimeZone();
//if(true)return 0;
// Date Part
datePart=datePart.toLowerCase().trim();
int dp;
if("s".equals(datePart)) return diffSeconds(msLeft, msRight);
else if("n".equals(datePart)) return diffSeconds(msLeft, msRight)/60L;
else if("h".equals(datePart)) return diffSeconds(msLeft, msRight)/3600L;
else if("d".equals(datePart)) dp=DATEPART_D;
else if("y".equals(datePart)) dp=DATEPART_Y;
else if("yyyy".equals(datePart))dp=DATEPART_YYYY;
else if("m".equals(datePart)) dp=DATEPART_M;
else if("w".equals(datePart)) dp=DATEPART_W;
else if("ww".equals(datePart)) dp=DATEPART_WW;
else if("q".equals(datePart)) dp=DATEPART_Q;
else throw new FunctionException(pc,"dateDiff",3,"datePart","invalid value ["+datePart+"], valid values has to be [q,s,n,h,d,m,y,yyyy,w,ww]");
// dates
Calendar _cLeft = JREDateTimeUtil.getThreadCalendar(tz);
_cLeft.setTimeInMillis(msLeft);
Calendar _cRight = JREDateTimeUtil.newInstance(tz);
_cRight.setTimeInMillis(msRight);
if(msLeft>msRight)
return -_call(pc,dp, _cRight, msRight, _cLeft, msLeft);
return _call(pc,dp, _cLeft, msLeft, _cRight, msRight);
//}
}
public static long diffSeconds(long msLeft, long msRight) {
if(msLeft>msRight)
return -(long)((msLeft-msRight)/1000D);
return (long)((msRight-msLeft)/1000D);
}
/*private static long _call(int datepart, long msLeft, long msRight) throws ExpressionException {
long msDiff = msRight-msLeft;
double diff = msDiff/1000D;
if(DATEPART_S==datepart) {
return (long) diff;
}
if(DATEPART_N==datepart) {
return (long)(diff/60D);
}
if(DATEPART_H==datepart) {
return (long)(diff/3600D);
}
return 0;
}*/
private static long _call(PageContext pc , int datepart, Calendar cLeft, long msLeft, Calendar cRight, long msRight) throws ExpressionException {
//long msDiff = msRight-msLeft;
//double diff = msDiff/1000D;
/*if(DATEPART_S==datepart) {
return (long) diff;
}
if(DATEPART_N==datepart) {
return (long)(diff/60D);
}
if(DATEPART_H==datepart) {
return (long)(diff/3600D);
}*/
long dDiff = cRight.get(Calendar.DATE)-cLeft.get(Calendar.DATE);
long hDiff = cRight.get(Calendar.HOUR_OF_DAY)-cLeft.get(Calendar.HOUR_OF_DAY);
long nDiff = cRight.get(Calendar.MINUTE)-cLeft.get(Calendar.MINUTE);
long sDiff = cRight.get(Calendar.SECOND)-cLeft.get(Calendar.SECOND);
if(DATEPART_D==datepart || DATEPART_W==datepart) {
int tmp=0;
if(hDiff<0) tmp=-1;
else if(hDiff>0);
else if(nDiff<0) tmp=-1;
else if(nDiff>0);
else if(sDiff<0) tmp=-1;
else if(sDiff>0);
long rst = dayDiff(cLeft, cRight)+tmp;
if(DATEPART_W==datepart)rst/=7;
return rst;
}
long yDiff = cRight.get(Calendar.YEAR)-cLeft.get(Calendar.YEAR);
long mDiff = cRight.get(Calendar.MONTH)-cLeft.get(Calendar.MONTH);
if(DATEPART_YYYY==datepart) {
int tmp=0;
if(mDiff<0) tmp=-1;
else if(mDiff>0);
else if(dDiff<0) tmp=-1;
else if(dDiff>0);
else if(hDiff<0) tmp=-1;
else if(hDiff>0);
else if(nDiff<0) tmp=-1;
else if(nDiff>0);
else if(sDiff<0) tmp=-1;
else if(sDiff>0);
return yDiff+tmp;
}
if(DATEPART_M==datepart || DATEPART_Q==datepart) {
int tmp=0;
if(dDiff<0) tmp=-1;
else if(dDiff>0);
else if(hDiff<0) tmp=-1;
else if(hDiff>0);
else if(nDiff<0) tmp=-1;
else if(nDiff>0);
else if(sDiff<0) tmp=-1;
else if(sDiff>0);
long rst = mDiff+(yDiff*12)+tmp;
if(DATEPART_Q==datepart)rst/=3;
return rst;
}
if(DATEPART_D==datepart) {
long rst = dDiff;
//if(DATEPART_Q==datepart)rst/=3;
return rst;
}
throw new FunctionException(pc,"dateDiff",3,"datePart","invalid value, valid values has to be [q,s,n,h,d,m,y,yyyy,w,ww]");
}
private static long dayDiff(Calendar l, Calendar r) {
int lYear = l.get(Calendar.YEAR);
int rYear = r.get(Calendar.YEAR);
int lDayOfYear=l.get(Calendar.DAY_OF_YEAR);
int rDayOfYear=r.get(Calendar.DAY_OF_YEAR);
// same year
if(lYear==rYear){
return rDayOfYear-lDayOfYear;
}
long diff=rDayOfYear;
diff-=lDayOfYear;
for(int year=lYear;year<rYear;year++){
diff+=Decision.isLeapYear(year)?366L:365L;
}
return diff;
}
}