001 /** 002 * Implements the CFML Function datediff 003 */ 004 package railo.runtime.functions.dateTime; 005 006 import java.util.Calendar; 007 import java.util.TimeZone; 008 009 import railo.commons.date.JREDateTimeUtil; 010 import railo.runtime.PageContext; 011 import railo.runtime.exp.ExpressionException; 012 import railo.runtime.exp.FunctionException; 013 import railo.runtime.ext.function.Function; 014 import railo.runtime.op.Decision; 015 import railo.runtime.type.dt.DateTime; 016 017 /** 018 * 019 */ 020 public final class DateDiff implements Function { 021 022 //private static final int DATEPART_S = 0; 023 //private static final int DATEPART_N = 1; 024 //private static final int DATEPART_H = 2; 025 private static final int DATEPART_D = 3; 026 private static final int DATEPART_Y = DATEPART_D; 027 private static final int DATEPART_YYYY = 10; 028 private static final int DATEPART_M = 11; 029 private static final int DATEPART_W = 12; 030 private static final int DATEPART_WW = DATEPART_W; 031 private static final int DATEPART_Q = 20; 032 033 private static Calendar _cRight; 034 private static Calendar _cLeft; 035 036 037 /** 038 * @param pc 039 * @param s 040 * @param date 041 * @param date1 042 * @return 043 * @throws ExpressionException 044 */ 045 public synchronized static double call(PageContext pc , String datePart, DateTime left, DateTime right) throws ExpressionException { 046 long msLeft = left.getTime(); 047 long msRight = right.getTime(); 048 TimeZone tz = pc.getTimeZone(); 049 //if(true)return 0; 050 // Date Part 051 datePart=datePart.toLowerCase().trim(); 052 int dp; 053 if("s".equals(datePart)) return diffSeconds(msLeft, msRight); 054 else if("n".equals(datePart)) return diffSeconds(msLeft, msRight)/60L; 055 else if("h".equals(datePart)) return diffSeconds(msLeft, msRight)/3600L; 056 else if("d".equals(datePart)) dp=DATEPART_D; 057 else if("y".equals(datePart)) dp=DATEPART_Y; 058 else if("yyyy".equals(datePart))dp=DATEPART_YYYY; 059 else if("m".equals(datePart)) dp=DATEPART_M; 060 else if("w".equals(datePart)) dp=DATEPART_W; 061 else if("ww".equals(datePart)) dp=DATEPART_WW; 062 else if("q".equals(datePart)) dp=DATEPART_Q; 063 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]"); 064 065 066 067 // dates 068 if(_cLeft==null) _cLeft = JREDateTimeUtil.newInstance(tz); 069 //synchronized(_cLeft){ 070 _cLeft.clear(); 071 _cLeft.setTimeZone(tz); 072 _cLeft.setTimeInMillis(msLeft); 073 //long msLeft = _cLeft.getTimeInMillis(); 074 075 if(_cRight==null) _cRight = JREDateTimeUtil.newInstance(tz); 076 else { 077 _cRight.clear(); 078 _cRight.setTimeZone(tz); 079 } 080 _cRight.setTimeInMillis(msRight); 081 //long msRight = _cRight.getTimeInMillis(); 082 083 084 if(msLeft>msRight) 085 return -_call(pc,dp, _cRight, msRight, _cLeft, msLeft); 086 087 return _call(pc,dp, _cLeft, msLeft, _cRight, msRight); 088 //} 089 } 090 091 public static long diffSeconds(long msLeft, long msRight) { 092 if(msLeft>msRight) 093 return -(long)((msLeft-msRight)/1000D); 094 return (long)((msRight-msLeft)/1000D); 095 } 096 097 /*private static long _call(int datepart, long msLeft, long msRight) throws ExpressionException { 098 099 long msDiff = msRight-msLeft; 100 double diff = msDiff/1000D; 101 if(DATEPART_S==datepart) { 102 return (long) diff; 103 } 104 if(DATEPART_N==datepart) { 105 return (long)(diff/60D); 106 } 107 if(DATEPART_H==datepart) { 108 return (long)(diff/3600D); 109 } 110 return 0; 111 }*/ 112 113 private static long _call(PageContext pc , int datepart, Calendar cLeft, long msLeft, Calendar cRight, long msRight) throws ExpressionException { 114 115 //long msDiff = msRight-msLeft; 116 //double diff = msDiff/1000D; 117 /*if(DATEPART_S==datepart) { 118 return (long) diff; 119 } 120 if(DATEPART_N==datepart) { 121 return (long)(diff/60D); 122 } 123 if(DATEPART_H==datepart) { 124 return (long)(diff/3600D); 125 }*/ 126 127 long dDiff = cRight.get(Calendar.DATE)-cLeft.get(Calendar.DATE); 128 long hDiff = cRight.get(Calendar.HOUR_OF_DAY)-cLeft.get(Calendar.HOUR_OF_DAY); 129 long nDiff = cRight.get(Calendar.MINUTE)-cLeft.get(Calendar.MINUTE); 130 long sDiff = cRight.get(Calendar.SECOND)-cLeft.get(Calendar.SECOND); 131 132 133 if(DATEPART_D==datepart || DATEPART_W==datepart) { 134 135 int tmp=0; 136 if(hDiff<0) tmp=-1; 137 else if(hDiff>0); 138 else if(nDiff<0) tmp=-1; 139 else if(nDiff>0); 140 else if(sDiff<0) tmp=-1; 141 else if(sDiff>0); 142 long rst = dayDiff(cLeft, cRight)+tmp; 143 if(DATEPART_W==datepart)rst/=7; 144 return rst; 145 } 146 147 long yDiff = cRight.get(Calendar.YEAR)-cLeft.get(Calendar.YEAR); 148 long mDiff = cRight.get(Calendar.MONTH)-cLeft.get(Calendar.MONTH); 149 if(DATEPART_YYYY==datepart) { 150 int tmp=0; 151 if(mDiff<0) tmp=-1; 152 else if(mDiff>0); 153 else if(dDiff<0) tmp=-1; 154 else if(dDiff>0); 155 else if(hDiff<0) tmp=-1; 156 else if(hDiff>0); 157 else if(nDiff<0) tmp=-1; 158 else if(nDiff>0); 159 else if(sDiff<0) tmp=-1; 160 else if(sDiff>0); 161 return yDiff+tmp; 162 } 163 if(DATEPART_M==datepart || DATEPART_Q==datepart) { 164 165 int tmp=0; 166 if(dDiff<0) tmp=-1; 167 else if(dDiff>0); 168 else if(hDiff<0) tmp=-1; 169 else if(hDiff>0); 170 else if(nDiff<0) tmp=-1; 171 else if(nDiff>0); 172 else if(sDiff<0) tmp=-1; 173 else if(sDiff>0); 174 long rst = mDiff+(yDiff*12)+tmp; 175 if(DATEPART_Q==datepart)rst/=3; 176 return rst; 177 } 178 if(DATEPART_D==datepart) { 179 180 long rst = dDiff; 181 //if(DATEPART_Q==datepart)rst/=3; 182 return rst; 183 } 184 185 186 throw new FunctionException(pc,"dateDiff",3,"datePart","invalid value, valid values has to be [q,s,n,h,d,m,y,yyyy,w,ww]"); 187 188 } 189 190 191 192 private static long dayDiff(Calendar l, Calendar r) { 193 int lYear = l.get(Calendar.YEAR); 194 int rYear = r.get(Calendar.YEAR); 195 int lDayOfYear=l.get(Calendar.DAY_OF_YEAR); 196 int rDayOfYear=r.get(Calendar.DAY_OF_YEAR); 197 198 199 // same year 200 if(lYear==rYear){ 201 return rDayOfYear-lDayOfYear; 202 } 203 204 long diff=rDayOfYear; 205 diff-=lDayOfYear; 206 for(int year=lYear;year<rYear;year++){ 207 diff+=Decision.isLeapYear(year)?366L:365L; 208 } 209 return diff; 210 } 211 212 }