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