package railo.runtime.functions.displayFormatting;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import railo.commons.date.TimeZoneUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.PageContext;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.functions.BIF;
import railo.runtime.op.Caster;
import railo.runtime.type.dt.DateTime;
/**
* Implements the CFML Function dateformat
*/
public final class DateTimeFormat extends BIF {
private static final long serialVersionUID = 134840879454373440L;
public static final String DEFAULT_MASK = "dd-MMM-yyyy HH:mm:ss";
private static final String[] AP = new String[]{"A","P"};
/**
* @param pc
* @param object
* @return Formated Time Object as String
* @throws ExpressionException
*/
public static String call(PageContext pc , Object object) throws ExpressionException {
return invoke(pc,object, null,Locale.US,ThreadLocalPageContext.getTimeZone(pc));
}
/**
* @param pc
* @param object
* @param mask Characters that show how CFML displays a date:
* @return Formated Time Object as String
* @throws ExpressionException
*/
public static String call(PageContext pc , Object object, String mask) throws ExpressionException {
return invoke(pc,object,mask,Locale.US,ThreadLocalPageContext.getTimeZone(pc));
}
public static String call(PageContext pc , Object object, String mask,String strTimezone) throws ExpressionException {
return invoke(pc,object,mask, Locale.US,strTimezone==null?ThreadLocalPageContext.getTimeZone(pc):TimeZoneUtil.toTimeZone(strTimezone));
}
public static String invoke(PageContext pc , Object object, String mask,Locale locale,TimeZone tz) throws ExpressionException {
if(locale==null) locale=Locale.US;
DateTime datetime = Caster.toDate(object,true,tz,null);
if(datetime==null) {
if(object.toString().trim().length()==0) return "";
throw new ExpressionException("can't convert value "+object+" to a datetime value");
}
java.text.DateFormat format=null;
if("short".equalsIgnoreCase(mask))
format=java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.SHORT, java.text.DateFormat.SHORT, locale);
else if("medium".equalsIgnoreCase(mask))
format=java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.MEDIUM, java.text.DateFormat.MEDIUM, locale);
else if("long".equalsIgnoreCase(mask))
format=java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.LONG, java.text.DateFormat.LONG, locale);
else if("full".equalsIgnoreCase(mask))
format=java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.FULL, java.text.DateFormat.FULL, locale);
else {
SimpleDateFormat sdf;
format = sdf= new SimpleDateFormat(convertMask(mask), locale);
if(mask!=null && StringUtil.indexOfIgnoreCase(mask, "tt")==-1 && StringUtil.indexOfIgnoreCase(mask, "t")!=-1) {
DateFormatSymbols dfs = new DateFormatSymbols(locale);
dfs.setAmPmStrings(AP);
sdf.setDateFormatSymbols(dfs);
}
}
format.setTimeZone(tz);
return format.format(datetime);
}
@Override
public Object invoke(PageContext pc, Object[] args) throws PageException {
if(args.length==1)return call(pc,args[0]);
if(args.length==2)return call(pc,args[0],Caster.toString(args[1]));
return call(pc,args[0],Caster.toString(args[1]),Caster.toString(args[2]));
}
private static String convertMask(String mask) {
if(mask==null) return DEFAULT_MASK;
boolean inside=false;
char[] carr = mask.toCharArray();
StringBuilder sb=new StringBuilder();
for(int i=0;i<carr.length;i++){
switch(carr[i]){
case 'm': if(!inside){sb.append('M');}else{sb.append(carr[i]);} break;
case 'S': if(!inside){sb.append('s');}else{sb.append(carr[i]);} break;
case 't': if(!inside){sb.append('a');}else{sb.append(carr[i]);} break;
case 'T': if(!inside){sb.append('a');}else{sb.append(carr[i]);} break;
case 'n': if(!inside){sb.append('m');}else{sb.append(carr[i]);} break;
case 'N': if(!inside){sb.append('m');}else{sb.append(carr[i]);} break;
case 'l': if(!inside){sb.append('S');}else{sb.append(carr[i]);} break;
case 'L': if(!inside){sb.append('S');}else{sb.append(carr[i]);} break;
case 'f': if(!inside){sb.append("'f'");}else{sb.append(carr[i]);} break;
case 'e': if(!inside){sb.append("'e'");}else{sb.append(carr[i]);} break;
case 'G':
case 'y':
case 'M':
case 'W':
case 'w':
case 'D':
case 'd':
case 'F':
case 'E':
case 'a':
case 'H':
case 'h':
case 'K':
case 'k':
case 'Z':
case 'z':
case 's':
//case '.':
sb.append(carr[i]);
break;
case '\'':
if(carr.length-1>i) {
if(carr[i+1]=='\'') {
i++;
sb.append("''");
break;
}
}
inside=!inside;
sb.append(carr[i]);
break;
/*case '\'':
if(carr.length-1>i) {
if(carr[i+1]=='\'') {
i++;
sb.append("''");
break;
}
}
sb.append("''");
break;*/
default:
char c=carr[i];
if(!inside && ((c>='a' && c<='z') || (c>='A' && c<='Z')))
sb.append('\'').append(c).append('\'');
else
sb.append(c);
}
}
return sb.toString();
}
}