001    package railo.runtime.format;
002    
003    import java.text.DateFormat;
004    import java.util.Calendar;
005    import java.util.Date;
006    import java.util.Locale;
007    import java.util.TimeZone;
008    
009    import railo.commons.date.JREDateTimeUtil;
010    import railo.commons.lang.StringUtil;
011    import railo.runtime.engine.ThreadLocalPageContext;
012    import railo.runtime.functions.dateTime.Beat;
013    import railo.runtime.op.Caster;
014    import railo.runtime.type.dt.DateTime;
015    import railo.runtime.type.dt.DateTimeImpl;
016    
017    public final class TimeFormat extends BaseFormat implements Format {
018            
019            private final Calendar calendar;
020            
021            
022            /**
023             * constructor of the class
024             * @param locale
025             */
026            public TimeFormat(Locale locale) {
027                    super(locale);
028                    calendar=JREDateTimeUtil.newInstance(locale); 
029            }
030            
031    
032            /**
033             * formats a date to a cfml date format (short)
034             * @param date
035             * @return formated date
036             */
037            public String format(Date date) {
038                    return format(date,"short");
039            }
040            
041            /**
042             * formats a date to a cfml date format
043             * @param date
044             * @param mask
045             * @return formated date
046             */
047            public String format(Date date,String mask) {
048                    DateTime dt=(date instanceof DateTime)?(DateTime)date:new DateTimeImpl(date.getTime(),false);
049                    return format(dt,mask,null);
050            }
051            
052            
053            public String format(DateTime date,String mask, TimeZone tz) {
054                    //DateUtil.setTimeZone(null,calendar,date); 
055                    calendar.setTimeZone(tz=ThreadLocalPageContext.getTimeZone(tz));  
056                    calendar.setTime(date);     
057                    
058    
059                    String lcMask=StringUtil.toLowerCase(mask);
060                    if(lcMask.equals("short"))                      return getAsString(DateFormat.SHORT,tz);
061                    else if(lcMask.equals("medium"))        return getAsString(DateFormat.MEDIUM,tz);
062                    else if(lcMask.equals("long"))          return getAsString(DateFormat.LONG,tz);
063                    else if(lcMask.equals("full"))          return getAsString(DateFormat.FULL,tz);
064                    else if(lcMask.equals("beat"))  {
065                            return Caster.toString(Beat.format(date)); 
066                    }
067                    
068                    int len=mask.length();
069                    int pos=0;
070                    if(len==0) return "";
071                    
072                    StringBuffer formated=new StringBuffer();
073                    
074                    
075                    
076                    for(;pos<len;pos++) {
077                            char c=mask.charAt(pos);
078                            char next=(len>pos+1)?mask.charAt(pos+1):(char)0;
079                            
080                            switch(c) {
081    
082                            // h: Hours; no leading zero for single-digit hours (12-hour clock) 
083                            // hh: Hours; leading zero for single-digit hours. (12-hour clock) 
084                                    case 'h':
085                                            int hour1=calendar.get(Calendar.HOUR_OF_DAY);
086                                            if(hour1==0)hour1=12;
087                                            if(hour1>12)hour1=hour1-12;
088                                            if(next=='h') {
089                                                    formated.append(hour1<10?"0"+hour1:""+hour1);
090                                                    pos++;
091                                            }
092                                            else {
093                                                    formated.append(hour1);
094                                            }                                       
095                                    break;
096    
097                            // H: Hours; no leading zero for single-digit hours (24-hour clock) 
098                            // HH: Hours; leading zero for single-digit hours (24-hour clock) 
099                                    case 'H':
100                                            int hour2=calendar.get(Calendar.HOUR_OF_DAY);
101                                            if(next=='H') {
102                                                    formated.append(hour2<10?"0"+hour2:""+hour2);
103                                                    pos++;
104                                            }
105                                            else {
106                                                    formated.append(hour2);
107                                            }                                       
108                                    break;
109    
110                            // m: Minutes; no leading zero for single-digit minutes 
111                            // mm: Minutes; leading zero for single-digit minutes 
112                                    case 'M':
113                                    case 'm':
114                                            int minute=calendar.get(Calendar.MINUTE);
115                                            if(next=='M' || next=='m') {
116                                                    formated.append(minute<10?"0"+minute:""+minute);
117                                                    pos++;
118                                            }
119                                            else {
120                                                    formated.append(minute);
121                                            }                                       
122                                    break;
123    
124                            // s: Seconds; no leading zero for single-digit seconds 
125                            // ss: Seconds; leading zero for single-digit seconds 
126                                    case 's':
127                                    case 'S':
128                                            int second=calendar.get(Calendar.SECOND);
129                                            if(next=='S' || next=='s') {
130                                                    formated.append(second<10?"0"+second:""+second);
131                                                    pos++;
132                                            }
133                                            else {
134                                                    formated.append(second);
135                                            }                                       
136                                    break;
137    
138                            // l: Milliseconds 
139                                    case 'l':
140                                    case 'L':
141                                            char nextnext=(len>pos+2)?mask.charAt(pos+2):(char)0;
142    
143                                            String millis=Caster.toString(calendar.get(Calendar.MILLISECOND));
144                                            if(next=='L' || next=='l') {
145                                                    if(millis.length()==1)millis="0"+millis;
146                                                    pos++;
147                                            }
148                                            if(nextnext=='L' || nextnext=='l') {
149                                                    if(millis.length()==2)millis="0"+millis;
150                                                    pos++;
151                                            }
152                                            formated.append(millis);        
153                                            
154                                            
155                                            
156                                    break;
157    
158                            // t: One-character time marker string, such as A or P. 
159                            // tt: Multiple-character time marker string, such as AM or PM 
160                                    case 't':
161                                    case 'T':
162                                            boolean isAm=calendar.get(Calendar.HOUR_OF_DAY)<12;
163                                            if(next=='T' || next=='t') {
164                                                    formated.append(isAm?"AM":"PM");
165                                                    pos++;
166                                            }
167                                            else {
168                                                    formated.append(isAm?"A":"P");
169                                            }                                       
170                                    break;
171                                    case 'z':
172                                    case 'Z':
173                                            // count next z and jump to last z (max 6)
174                                            int start=pos;
175                                            while((pos+1)<len && Character.toLowerCase(mask.charAt(pos+1))=='z'){
176                                                    pos++;
177                                                    if(pos-start>4)break;
178                                            }
179                                            if(pos-start>2)formated.append(tz.getDisplayName(getLocale()));      
180                                            else formated.append(tz.getID());       
181                                            
182                                    break;
183                                    
184                            // Otherwise
185                                    default:
186                                            formated.append(c);
187                            }
188                    }
189                    return formated.toString();
190            }
191    
192            private String getAsString(int style,TimeZone tz) {
193                    DateFormat df = DateFormat.getTimeInstance(style,getLocale());
194                    df.setTimeZone(tz);
195                    return df.format(calendar.getTime());   
196            }
197    
198    }