001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/** 020 * Implements the CFML Function datediff 021 */ 022package lucee.runtime.functions.dateTime; 023 024import java.util.Calendar; 025import java.util.Locale; 026import java.util.TimeZone; 027 028import lucee.commons.date.JREDateTimeUtil; 029import lucee.runtime.PageContext; 030import lucee.runtime.exp.ExpressionException; 031import lucee.runtime.exp.FunctionException; 032import lucee.runtime.ext.function.Function; 033import lucee.runtime.op.Decision; 034import lucee.runtime.type.dt.DateTime; 035 036/** 037 * 038 */ 039public final class DateDiff implements Function { 040 041 //private static final int DATEPART_S = 0; 042 //private static final int DATEPART_N = 1; 043 //private static final int DATEPART_H = 2; 044 private static final int DATEPART_D = 3; 045 private static final int DATEPART_Y = DATEPART_D; 046 private static final int DATEPART_YYYY = 10; 047 private static final int DATEPART_M = 11; 048 private static final int DATEPART_W = 12; 049 private static final int DATEPART_WW = DATEPART_W; 050 private static final int DATEPART_Q = 20; 051 052 //private static Calendar _cRight; 053 //private static Calendar _cLeft; 054 055 056 /** 057 * @param pc 058 * @param s 059 * @param date 060 * @param date1 061 * @return 062 * @throws ExpressionException 063 */ 064 public synchronized static double call(PageContext pc , String datePart, DateTime left, DateTime right) throws ExpressionException { 065 long msLeft = left.getTime(); 066 long msRight = right.getTime(); 067 TimeZone tz = pc.getTimeZone(); 068 //if(true)return 0; 069 // Date Part 070 datePart=datePart.toLowerCase().trim(); 071 int dp; 072 if("s".equals(datePart)) return diffSeconds(msLeft, msRight); 073 else if("n".equals(datePart)) return diffSeconds(msLeft, msRight)/60L; 074 else if("h".equals(datePart)) return diffSeconds(msLeft, msRight)/3600L; 075 else if("d".equals(datePart)) dp=DATEPART_D; 076 else if("y".equals(datePart)) dp=DATEPART_Y; 077 else if("yyyy".equals(datePart))dp=DATEPART_YYYY; 078 else if("m".equals(datePart)) dp=DATEPART_M; 079 else if("w".equals(datePart)) dp=DATEPART_W; 080 else if("ww".equals(datePart)) dp=DATEPART_WW; 081 else if("q".equals(datePart)) dp=DATEPART_Q; 082 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]"); 083 084 085 086 // dates 087 Calendar _cLeft = JREDateTimeUtil.getThreadCalendar(tz); 088 _cLeft.setTimeInMillis(msLeft); 089 090 Calendar _cRight = JREDateTimeUtil.newInstance(tz,Locale.US); 091 _cRight.setTimeInMillis(msRight); 092 093 094 if(msLeft>msRight) 095 return -_call(pc,dp, _cRight, msRight, _cLeft, msLeft); 096 097 return _call(pc,dp, _cLeft, msLeft, _cRight, msRight); 098 //} 099 } 100 101 public static long diffSeconds(long msLeft, long msRight) { 102 if(msLeft>msRight) 103 return -(long)((msLeft-msRight)/1000D); 104 return (long)((msRight-msLeft)/1000D); 105 } 106 107 /*private static long _call(int datepart, long msLeft, long msRight) throws ExpressionException { 108 109 long msDiff = msRight-msLeft; 110 double diff = msDiff/1000D; 111 if(DATEPART_S==datepart) { 112 return (long) diff; 113 } 114 if(DATEPART_N==datepart) { 115 return (long)(diff/60D); 116 } 117 if(DATEPART_H==datepart) { 118 return (long)(diff/3600D); 119 } 120 return 0; 121 }*/ 122 123 private static long _call(PageContext pc , int datepart, Calendar cLeft, long msLeft, Calendar cRight, long msRight) throws ExpressionException { 124 125 //long msDiff = msRight-msLeft; 126 //double diff = msDiff/1000D; 127 /*if(DATEPART_S==datepart) { 128 return (long) diff; 129 } 130 if(DATEPART_N==datepart) { 131 return (long)(diff/60D); 132 } 133 if(DATEPART_H==datepart) { 134 return (long)(diff/3600D); 135 }*/ 136 137 long dDiff = cRight.get(Calendar.DATE)-cLeft.get(Calendar.DATE); 138 long hDiff = cRight.get(Calendar.HOUR_OF_DAY)-cLeft.get(Calendar.HOUR_OF_DAY); 139 long nDiff = cRight.get(Calendar.MINUTE)-cLeft.get(Calendar.MINUTE); 140 long sDiff = cRight.get(Calendar.SECOND)-cLeft.get(Calendar.SECOND); 141 142 143 if(DATEPART_D==datepart || DATEPART_W==datepart) { 144 145 int tmp=0; 146 if(hDiff<0) tmp=-1; 147 else if(hDiff>0); 148 else if(nDiff<0) tmp=-1; 149 else if(nDiff>0); 150 else if(sDiff<0) tmp=-1; 151 else if(sDiff>0); 152 long rst = dayDiff(cLeft, cRight)+tmp; 153 if(DATEPART_W==datepart)rst/=7; 154 return rst; 155 } 156 157 long yDiff = cRight.get(Calendar.YEAR)-cLeft.get(Calendar.YEAR); 158 long mDiff = cRight.get(Calendar.MONTH)-cLeft.get(Calendar.MONTH); 159 if(DATEPART_YYYY==datepart) { 160 int tmp=0; 161 if(mDiff<0) tmp=-1; 162 else if(mDiff>0); 163 else if(dDiff<0) tmp=-1; 164 else if(dDiff>0); 165 else if(hDiff<0) tmp=-1; 166 else if(hDiff>0); 167 else if(nDiff<0) tmp=-1; 168 else if(nDiff>0); 169 else if(sDiff<0) tmp=-1; 170 else if(sDiff>0); 171 return yDiff+tmp; 172 } 173 if(DATEPART_M==datepart || DATEPART_Q==datepart) { 174 175 int tmp=0; 176 if(dDiff<0) tmp=-1; 177 else if(dDiff>0); 178 else if(hDiff<0) tmp=-1; 179 else if(hDiff>0); 180 else if(nDiff<0) tmp=-1; 181 else if(nDiff>0); 182 else if(sDiff<0) tmp=-1; 183 else if(sDiff>0); 184 long rst = mDiff+(yDiff*12)+tmp; 185 if(DATEPART_Q==datepart)rst/=3; 186 return rst; 187 } 188 if(DATEPART_D==datepart) { 189 190 long rst = dDiff; 191 //if(DATEPART_Q==datepart)rst/=3; 192 return rst; 193 } 194 195 196 throw new FunctionException(pc,"dateDiff",3,"datePart","invalid value, valid values has to be [q,s,n,h,d,m,y,yyyy,w,ww]"); 197 198 } 199 200 201 202 private static long dayDiff(Calendar l, Calendar r) { 203 int lYear = l.get(Calendar.YEAR); 204 int rYear = r.get(Calendar.YEAR); 205 int lDayOfYear=l.get(Calendar.DAY_OF_YEAR); 206 int rDayOfYear=r.get(Calendar.DAY_OF_YEAR); 207 208 209 // same year 210 if(lYear==rYear){ 211 return rDayOfYear-lDayOfYear; 212 } 213 214 long diff=rDayOfYear; 215 diff-=lDayOfYear; 216 for(int year=lYear;year<rYear;year++){ 217 diff+=Decision.isLeapYear(year)?366L:365L; 218 } 219 return diff; 220 } 221 222}