/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
**/
package lucee.runtime.format;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import lucee.commons.date.JREDateTimeUtil;
import lucee.commons.lang.StringUtil;
import lucee.runtime.functions.dateTime.Beat;
import lucee.runtime.op.Caster;
import lucee.runtime.type.dt.DateTime;
import lucee.runtime.type.dt.DateTimeImpl;
public final class TimeFormat extends BaseFormat implements Format {
/**
* constructor of the class
* @param locale
*/
public TimeFormat(Locale locale) {
super(locale);
}
/**
* formats a date to a cfml date format (short)
* @param date
* @return formated date
*/
@Override
public String format(Date date) {
return format(date,"short");
}
/**
* formats a date to a cfml date format
* @param date
* @param mask
* @return formated date
*/
@Override
public String format(Date date,String mask) {
DateTime dt=(date instanceof DateTime)?(DateTime)date:new DateTimeImpl(date.getTime(),false);
return format(dt,mask,null);
}
public String format(DateTime date,String mask, TimeZone tz) {
return format(date.getTime(), mask, tz);
}
public String format(long time,String mask, TimeZone tz) {
Calendar calendar = JREDateTimeUtil.getThreadCalendar(getLocale(),tz);
calendar.setTimeInMillis(time);
String lcMask=StringUtil.toLowerCase(mask);
if(lcMask.equals("short")) return getAsString(calendar,DateFormat.SHORT,tz);
else if(lcMask.equals("medium")) return getAsString(calendar,DateFormat.MEDIUM,tz);
else if(lcMask.equals("long")) return getAsString(calendar,DateFormat.LONG,tz);
else if(lcMask.equals("full")) return getAsString(calendar,DateFormat.FULL,tz);
else if(lcMask.equals("beat")) {
return Caster.toString(Beat.format(time));
}
int len=mask.length();
int pos=0;
if(len==0) return "";
StringBuilder formated=new StringBuilder();
for(;pos<len;pos++) {
char c=mask.charAt(pos);
char next=(len>pos+1)?mask.charAt(pos+1):(char)0;
switch(c) {
case 'z':{
int count=1;
while(mask.length()>pos+1 && mask.charAt(pos+1)=='z') {
pos++;
count++;
}
formated.append(lucee.runtime.format.DateFormat.z(time,tz,count));
}
break;
// RFC 822 TimeZone
case 'Z':{
int count=1;
while(mask.length()>pos+1 && mask.charAt(pos+1)=='Z') {
pos++;
count++;
}
formated.append(lucee.runtime.format.DateFormat.Z(time,tz));
}
break;
// ISO 8601 TimeZone
case 'X':{
int count=1;
while(mask.length()>pos+1 && mask.charAt(pos+1)=='X') {
pos++;
count++;
}
TimeZone.setDefault(TimeZone.getTimeZone("CET"));
formated.append(lucee.runtime.format.DateFormat.X(time,tz,count));
}
break;
// h: Hours; no leading zero for single-digit hours (12-hour clock)
// hh: Hours; leading zero for single-digit hours. (12-hour clock)
case 'h':
int hour1=calendar.get(Calendar.HOUR_OF_DAY);
if(hour1==0)hour1=12;
if(hour1>12)hour1=hour1-12;
if(next=='h') {
formated.append(hour1<10?"0"+hour1:""+hour1);
pos++;
}
else {
formated.append(hour1);
}
break;
// H: Hours; no leading zero for single-digit hours (24-hour clock)
// HH: Hours; leading zero for single-digit hours (24-hour clock)
case 'H':
int hour2=calendar.get(Calendar.HOUR_OF_DAY);
if(next=='H') {
formated.append(hour2<10?"0"+hour2:""+hour2);
pos++;
}
else {
formated.append(hour2);
}
break;
// m: Minutes; no leading zero for single-digit minutes
// mm: Minutes; leading zero for single-digit minutes
case 'M':
case 'm':
int minute=calendar.get(Calendar.MINUTE);
if(next=='M' || next=='m') {
formated.append(minute<10?"0"+minute:""+minute);
pos++;
}
else {
formated.append(minute);
}
break;
// s: Seconds; no leading zero for single-digit seconds
// ss: Seconds; leading zero for single-digit seconds
case 's':
case 'S':
int second=calendar.get(Calendar.SECOND);
if(next=='S' || next=='s') {
formated.append(second<10?"0"+second:""+second);
pos++;
}
else {
formated.append(second);
}
break;
// l: Milliseconds
case 'l':
case 'L':
char nextnext=(len>pos+2)?mask.charAt(pos+2):(char)0;
String millis=Caster.toString(calendar.get(Calendar.MILLISECOND));
if(next=='L' || next=='l') {
if(millis.length()==1)millis="0"+millis;
pos++;
}
if(nextnext=='L' || nextnext=='l') {
if(millis.length()==2)millis="0"+millis;
pos++;
}
formated.append(millis);
break;
// t: One-character time marker string, such as A or P.
// tt: Multiple-character time marker string, such as AM or PM
case 't':
case 'T':
boolean isAm=calendar.get(Calendar.HOUR_OF_DAY)<12;
if(next=='T' || next=='t') {
formated.append(isAm?"AM":"PM");
pos++;
}
else {
formated.append(isAm?"A":"P");
}
break;
/*case 'z':
case 'Z':
// count next z and jump to last z (max 6)
int start=pos;
while((pos+1)<len && Character.toLowerCase(mask.charAt(pos+1))=='z'){
pos++;
if(pos-start>4)break;
}
if(pos-start>2)formated.append(tz.getDisplayName(getLocale()));
else formated.append(tz.getID());
break;*/
// Otherwise
default:
formated.append(c);
}
}
return formated.toString();
}
private String getAsString(Calendar c, int style,TimeZone tz) {
DateFormat df = DateFormat.getTimeInstance(style,getLocale());
df.setTimeZone(tz);
return df.format(c.getTime());
}
}