001    package railo.runtime.format;
002    
003    import java.util.Calendar;
004    import java.util.Date;
005    import java.util.Locale;
006    import java.util.TimeZone;
007    
008    import railo.commons.date.JREDateTimeUtil;
009    import railo.commons.lang.StringUtil;
010    import railo.runtime.engine.ThreadLocalPageContext;
011    import railo.runtime.op.Caster;
012    
013    public final class DateTimeFormat extends BaseFormat implements Format {
014            
015            private final Calendar calendar;
016            
017            /**
018             * constructor of the class
019             * @param locale
020             */
021            public DateTimeFormat(Locale locale) {
022                    super(locale);
023                    calendar=JREDateTimeUtil.newInstance(locale);
024            }
025            
026    
027            /**
028             * formats a date to a cfml date format (short)
029             * @param date
030             * @return formated date
031             */
032            public String format(Date date) {
033                    return format(date,"medium");
034            }
035            
036            /**
037             * formats a date to a cfml date format
038             * @param date
039             * @param mask
040             * @return formated date as string
041             */
042            public String format(Date date,String mask) {
043                    return format(date,mask,null);
044            }
045            public String format(Date date,String mask, TimeZone tz) {
046                    //DateUtil.setTimeZone(null,calendar,date); 
047                    calendar.setTimeZone(tz=ThreadLocalPageContext.getTimeZone(tz));  
048                    calendar.setTime(date);     
049                    
050    
051                    String lcMask=StringUtil.toLowerCase(mask);
052                    if(lcMask.equals("short"))                      return getAsString(java.text.DateFormat.SHORT,tz);
053                    else if(lcMask.equals("medium"))                return getAsString(java.text.DateFormat.MEDIUM,tz);
054                    else if(lcMask.equals("long"))          return getAsString(java.text.DateFormat.LONG,tz);
055                    else if(lcMask.equals("full"))          return getAsString(java.text.DateFormat.FULL,tz);
056                    
057                    int len=mask.length();
058                    int pos=0;
059                    if(len==0) return "";
060                    
061                    StringBuffer formated=new StringBuffer();
062                    
063                    
064                    
065                    for(;pos<len;pos++) {
066                            char c=mask.charAt(pos);
067                            char next=(len>pos+1)?mask.charAt(pos+1):(char)0;
068                            switch(c) {
069    
070                            // d: Day of month. Digits; no leading zero for single-digit days 
071                            // dd: Day of month. Digits; leading zero for single-digit days 
072                            // ddd: Day of week, abbreviation 
073                            // dddd: Day of week. Full name 
074                                    case 'd':
075                                    case 'D':
076                                            char next2=(len>pos+2)?mask.charAt(pos+2):(char)0;
077                                            char next3=(len>pos+3)?mask.charAt(pos+3):(char)0;
078                                            
079                                            int day=calendar.get(Calendar.DATE);
080                                            if(next=='d' || next=='D') {
081                                                    if(next2=='d' || next2=='D') {
082                                                            if(next3=='d' || next3=='D') {
083                                                                    formated.append(getDayOfWeekAsString(calendar.get(Calendar.DAY_OF_WEEK)));
084                                                                    pos+=3;
085                                                            }
086                                                            else {
087                                                                    formated.append(getDayOfWeekShortAsString(calendar.get(Calendar.DAY_OF_WEEK)));
088                                                                    pos+=2;                                                         
089                                                            }
090                                                    }
091                                                    else {
092                                                            formated.append(day<10?"0"+day:""+day);
093                                                            pos++;
094                                                    }
095                                            }
096                                            else {
097                                                    formated.append(day);
098                                            }                                       
099                                    break;
100    
101                            // m: Month. Digits; no leading zero for single-digit months 
102                            // mm: Month. Digits; leading zero for single-digit months 
103                            // mmm: Month. abbreviation (if appropriate) 
104                            // mmmm: Month. Full name 
105                                    case 'm':
106                                    case 'M':
107                                            char next_2=(len>pos+2)?mask.charAt(pos+2):(char)0;
108                                            char next_3=(len>pos+3)?mask.charAt(pos+3):(char)0;
109                                            
110                                            int month=calendar.get(Calendar.MONTH)+1;
111                                            if(next=='m' || next=='M') {
112                                                    if(next_2=='m' || next_2=='M') {
113                                                            if(next_3=='m' || next_3=='M') {
114                                                                    formated.append(getMonthAsString(month));
115                                                                    pos+=3;
116                                                            }
117                                                            else {
118                                                                    formated.append(getMonthShortAsString(month));
119                                                                    pos+=2;                                                         
120                                                            }
121                                                    }
122                                                    else {
123                                                            formated.append(month<10?"0"+month:""+month);
124                                                            pos++;
125                                                    }
126                                            }
127                                            else {
128                                                    formated.append(month);
129                                            }                                       
130                                    break;
131    
132                            // y: Year. Last two digits; no leading zero for years less than 10 
133                            // yy: Year. Last two digits; leading zero for years less than 10 
134                            // yyyy: Year. Four digits 
135                                    case 'y':
136                                    case 'Y':
137                                            char next__2=(len>pos+2)?mask.charAt(pos+2):(char)0;
138                                            char next__3=(len>pos+3)?mask.charAt(pos+3):(char)0;
139                                            
140                                            int year4=calendar.get(Calendar.YEAR);
141                                            int year2=year4%100;
142                                            if(next=='y' || next=='Y') {
143                                                    if((next__2=='y' || next__2=='Y') && (next__3=='y' || next__3=='Y')) {
144                                                            formated.append(year4);
145                                                            pos+=3;
146                                                    }
147                                                    else {
148                                                            formated.append(year2<10?"0"+year2:""+year2);
149                                                            pos++;
150                                                    }
151                                            }
152                                            else {
153                                                    formated.append(year2);
154                                            }                                       
155                                    break;
156                                    
157    
158    
159                                    // h: Hours; no leading zero for single-digit hours (12-hour clock) 
160                                    // hh: Hours; leading zero for single-digit hours. (12-hour clock) 
161                                            case 'h':
162                                                    int hour1=calendar.get(Calendar.HOUR_OF_DAY);
163                                                    if(hour1==0)hour1=12;
164                                                    if(hour1>12)hour1=hour1-12;
165                                                    if(next=='h') {
166                                                            formated.append(hour1<10?"0"+hour1:""+hour1);
167                                                            pos++;
168                                                    }
169                                                    else {
170                                                            formated.append(hour1);
171                                                    }                                       
172                                            break;
173    
174                                    // H: Hours; no leading zero for single-digit hours (24-hour clock) 
175                                    // HH: Hours; leading zero for single-digit hours (24-hour clock) 
176                                            case 'H':
177                                                    int hour2=calendar.get(Calendar.HOUR_OF_DAY);
178                                                    if(next=='H') {
179                                                            formated.append(hour2<10?"0"+hour2:""+hour2);
180                                                            pos++;
181                                                    }
182                                                    else {
183                                                            formated.append(hour2);
184                                                    }                                       
185                                            break;
186    
187                                    // n: Minutes; no leading zero for single-digit minutes 
188                                    // nn: Minutes; leading zero for single-digit minutes 
189                                            case 'N':
190                                            case 'n':
191                                                    int minute=calendar.get(Calendar.MINUTE);
192                                                    if(next=='N' || next=='n') {
193                                                            formated.append(minute<10?"0"+minute:""+minute);
194                                                            pos++;
195                                                    }
196                                                    else {
197                                                            formated.append(minute);
198                                                    }                                       
199                                            break;
200    
201                                    // s: Seconds; no leading zero for single-digit seconds 
202                                    // ss: Seconds; leading zero for single-digit seconds 
203                                            case 's':
204                                            case 'S':
205                                                    int second=calendar.get(Calendar.SECOND);
206                                                    if(next=='S' || next=='s') {
207                                                            formated.append(second<10?"0"+second:""+second);
208                                                            pos++;
209                                                    }
210                                                    else {
211                                                            formated.append(second);
212                                                    }                                       
213                                            break;
214    
215                                    // l: Milliseconds 
216                                            case 'l':
217                                            case 'L':
218                                                    char nextnext=(len>pos+2)?mask.charAt(pos+2):(char)0;
219    
220                                                    String millis=Caster.toString(calendar.get(Calendar.MILLISECOND));
221                                                    if(next=='L' || next=='l') {
222                                                            if(millis.length()==1)millis="0"+millis;
223                                                            pos++;
224                                                    }
225                                                    if(nextnext=='L' || nextnext=='l') {
226                                                            if(millis.length()==2)millis="0"+millis;
227                                                            pos++;
228                                                    }
229                                                    formated.append(millis);        
230                                                    
231                                                    
232                                                    
233                                            break;
234    
235                                    // t: One-character time marker string, such as A or P. 
236                                    // tt: Multiple-character time marker string, such as AM or PM 
237                                            case 't':
238                                            case 'T':
239                                                    boolean isAm=calendar.get(Calendar.HOUR_OF_DAY)<12;
240                                                    if(next=='T' || next=='t') {
241                                                            formated.append(isAm?"AM":"PM");
242                                                            pos++;
243                                                    }
244                                                    else {
245                                                            formated.append(isAm?"A":"P");
246                                                    }                                       
247                                            break;
248                                            case 'z':
249                                            case 'Z':
250                                                    // count next z and jump to last z (max 6)
251                                                    int start=pos;
252                                                    while((pos+1)<len && Character.toLowerCase(mask.charAt(pos+1))=='z'){
253                                                            pos++;
254                                                            if(pos-start>4)break;
255                                                    }
256                                                    if(pos-start>2)formated.append(tz.getDisplayName(getLocale()));      
257                                                    else formated.append(tz.getID());       
258                                                    
259                                            break;
260                                    
261                                    
262                                    
263                            // Otherwise
264                                    default:
265                                            formated.append(c);
266                            }
267                    }
268                    return formated.toString();
269            }
270            
271    
272            private String getAsString(int style, TimeZone tz) {
273                    java.text.DateFormat df = java.text.DateFormat.getDateTimeInstance(style,style,getLocale());
274                    df.setTimeZone(tz);
275                    return df.format(calendar.getTime());   
276            }
277    }