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 dateadd 021 */ 022package lucee.runtime.functions.dateTime; 023 024import java.util.Calendar; 025import java.util.TimeZone; 026 027import lucee.commons.date.JREDateTimeUtil; 028import lucee.runtime.PageContext; 029import lucee.runtime.exp.ExpressionException; 030import lucee.runtime.ext.function.Function; 031import lucee.runtime.type.dt.DateTime; 032import lucee.runtime.type.dt.DateTimeImpl; 033 034public final class DateAdd implements Function { 035 036 private static final long serialVersionUID = -5827644560609841341L; 037 038 public static DateTime call(PageContext pc , String datepart, double number, DateTime date) throws ExpressionException { 039 return _call(pc,pc.getTimeZone(), datepart, number, date); 040 } 041 042 public synchronized static DateTime _call(PageContext pc ,TimeZone tz, String datepart, double number, DateTime date) throws ExpressionException { 043 datepart=datepart.toLowerCase(); 044 long l=(long)number; 045 int n=(int) l; 046 char first=datepart.length()==1?datepart.charAt(0):(char)0; 047 048 if(first=='l') return new DateTimeImpl(pc,date.getTime()+l,false); 049 else if(first=='s') return new DateTimeImpl(pc,date.getTime()+(l*1000),false); 050 else if(first=='n') return new DateTimeImpl(pc,date.getTime()+(l*60000),false); 051 else if(first=='h') return new DateTimeImpl(pc,date.getTime()+(l*3600000),false); 052 053 054 Calendar c=JREDateTimeUtil.getThreadCalendar(); 055 //if (c == null)c=JREDateTimeUtil.newInstance(); 056 //synchronized (c) { 057 //c.clear(); 058 c.setTimeZone(tz); 059 c.setTimeInMillis(date.getTime()); 060 061 if(datepart.equals("yyyy")) { 062 c.set(Calendar.YEAR,c.get(Calendar.YEAR)+n); 063 } 064 else if(datepart.equals("ww")) c.add(Calendar.WEEK_OF_YEAR,n); 065 else if(first=='q') c.add(Calendar.MONTH,(n*3)); 066 else if(first=='m') c.add(Calendar.MONTH,n); 067 else if(first=='y') c.add(Calendar.DAY_OF_YEAR,n); 068 else if(first=='d') c.add(Calendar.DATE,n); 069 else if(first=='w') { 070 int dow = c.get(Calendar.DAY_OF_WEEK); 071 int offset; 072 // - 073 if(n < 0) { 074 if(Calendar.SUNDAY==dow) offset=2; 075 else offset=-(6-dow); 076 } 077 // + 078 else { 079 if(Calendar.SATURDAY==dow) offset=-2; 080 else offset=dow-2; 081 } 082 c.add(Calendar.DAY_OF_WEEK, -offset); 083 084 if(dow==Calendar.SATURDAY || dow==Calendar.SUNDAY) { 085 if(n>0) n--; 086 else if(n<0) n++; 087 } 088 else n+=offset; 089 c.add(Calendar.DAY_OF_WEEK, (n / 5) * 7 + n % 5); 090 091 } 092 093 else { 094 throw new ExpressionException("invalid datepart identifier ["+datepart+"] for function dateAdd"); 095 } 096 return new DateTimeImpl(pc,c.getTimeInMillis(),false); 097 //} 098 } 099}