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 **/
019package lucee.runtime.format;
020
021import java.util.Calendar;
022import java.util.Date;
023import java.util.Locale;
024import java.util.TimeZone;
025
026import lucee.commons.date.JREDateTimeUtil;
027import lucee.commons.lang.StringUtil;
028
029public final class DateFormat extends BaseFormat implements Format {
030        
031        /**
032         * constructor of the class
033         * @param locale
034         */
035        public DateFormat(Locale locale) {
036                super(locale);
037        }
038        
039
040        /**
041         * formats a date to a cfml date format (short)
042         * @param date
043         * @return formated date
044         */
045        public String format(Date date) {
046                return format(date,"medium");
047        }
048        
049        /**
050         * formats a date to a cfml date format
051         * @param date
052         * @param mask
053         * @return formated date as string
054         */
055        public String format(Date date,String mask) {
056                return format(date,mask,null);
057        }
058        public String format(Date date,String mask, TimeZone tz) {
059                return format(date.getTime(), mask, tz);
060        }
061        public String format(long time,String mask, TimeZone tz) {
062                Calendar calendar = JREDateTimeUtil.getThreadCalendar(getLocale(),tz);
063                calendar.setTimeInMillis(time);
064
065                String lcMask=StringUtil.toLowerCase(mask);
066                if(lcMask.equals("short"))                      return getAsString(calendar,java.text.DateFormat.SHORT,tz);
067                else if(lcMask.equals("medium"))                return getAsString(calendar,java.text.DateFormat.MEDIUM,tz);
068                else if(lcMask.equals("long"))          return getAsString(calendar,java.text.DateFormat.LONG,tz);
069                else if(lcMask.equals("full"))          return getAsString(calendar,java.text.DateFormat.FULL,tz);
070                
071                int len=mask.length();
072                int pos=0;
073                if(len==0) return "";
074                
075                StringBuilder formated=new StringBuilder();
076                
077                
078                
079                for(;pos<len;pos++) {
080                        char c=mask.charAt(pos);
081                        char next=(len>pos+1)?mask.charAt(pos+1):(char)0;
082                        switch(c) {
083
084                        // d: Day of month. Digits; no leading zero for single-digit days 
085                        // dd: Day of month. Digits; leading zero for single-digit days 
086                        // ddd: Day of week, abbreviation 
087                        // dddd: Day of week. Full name 
088                                case 'd':
089                                case 'D':
090                                        char next2=(len>pos+2)?mask.charAt(pos+2):(char)0;
091                                        char next3=(len>pos+3)?mask.charAt(pos+3):(char)0;
092                                        
093                                        int day=calendar.get(Calendar.DATE);
094                                        if(next=='d' || next=='D') {
095                                                if(next2=='d' || next2=='D') {
096                                                        if(next3=='d' || next3=='D') {
097                                                                formated.append(getDayOfWeekAsString(calendar.get(Calendar.DAY_OF_WEEK)));
098                                                                pos+=3;
099                                                        }
100                                                        else {
101                                                                formated.append(getDayOfWeekShortAsString(calendar.get(Calendar.DAY_OF_WEEK)));
102                                                                pos+=2;                                                         
103                                                        }
104                                                }
105                                                else {
106                                                        formated.append(day<10?"0"+day:""+day);
107                                                        pos++;
108                                                }
109                                        }
110                                        else {
111                                                formated.append(day);
112                                        }                                       
113                                break;
114
115                        // m: Month. Digits; no leading zero for single-digit months 
116                        // mm: Month. Digits; leading zero for single-digit months 
117                        // mmm: Month. abbreviation (if appropriate) 
118                        // mmmm: Month. Full name 
119                                case 'm':
120                                case 'M':
121                                        char next_2=(len>pos+2)?mask.charAt(pos+2):(char)0;
122                                        char next_3=(len>pos+3)?mask.charAt(pos+3):(char)0;
123                                        
124                                        int month=calendar.get(Calendar.MONTH)+1;
125                                        if(next=='m' || next=='M') {
126                                                if(next_2=='m' || next_2=='M') {
127                                                        if(next_3=='m' || next_3=='M') {
128                                                                formated.append(getMonthAsString(month));
129                                                                pos+=3;
130                                                        }
131                                                        else {
132                                                                formated.append(getMonthShortAsString(month));
133                                                                pos+=2;                                                         
134                                                        }
135                                                }
136                                                else {
137                                                        formated.append(month<10?"0"+month:""+month);
138                                                        pos++;
139                                                }
140                                        }
141                                        else {
142                                                formated.append(month);
143                                        }                                       
144                                break;
145
146                        // y: Year. Last two digits; no leading zero for years less than 10 
147                        // yy: Year. Last two digits; leading zero for years less than 10 
148                        // yyyy: Year. Four digits 
149                                case 'y':
150                                case 'Y':
151                                        char next__2=(len>pos+2)?mask.charAt(pos+2):(char)0;
152                                        char next__3=(len>pos+3)?mask.charAt(pos+3):(char)0;
153                                        
154                                        int year4=calendar.get(Calendar.YEAR);
155                                        int year2=year4%100;
156                                        if(next=='y' || next=='Y') {
157                                                if((next__2=='y' || next__2=='Y') && (next__3=='y' || next__3=='Y')) {
158                                                        formated.append(year4);
159                                                        pos+=3;
160                                                }
161                                                else {
162                                                        formated.append(year2<10?"0"+year2:""+year2);
163                                                        pos++;
164                                                }
165                                        }
166                                        else {
167                                                formated.append(year2);
168                                        }                                       
169                                break;
170                                
171                        // Otherwise
172                                default:
173                                        formated.append(c);
174                        }
175                }
176                return formated.toString();
177        }
178        
179
180        private String getAsString(Calendar c,int style, TimeZone tz) {
181                java.text.DateFormat df = java.text.DateFormat.getDateInstance(style,getLocale());
182                df.setTimeZone(tz);
183                return df.format(c.getTime());  
184        }
185        
186}