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