blob: 749b08bb693ca15e85438cad7b18aa9fc1530004 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.opensymphony.xwork2.conversion.impl;
import org.apache.struts2.conversion.TypeConversionException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
public class DateConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
Date result = null;
if (value instanceof String && value != null && ((String) value).length() > 0) {
String sa = (String) value;
Locale locale = getLocale(context);
DateFormat df = null;
if (java.sql.Time.class == toType) {
df = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale);
} else if (java.sql.Timestamp.class == toType) {
Date check = null;
SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.MEDIUM,
locale);
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT,
locale);
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
locale);
SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt};
for (SimpleDateFormat fmt : fmts) {
try {
check = fmt.parse(sa);
df = fmt;
if (check != null) {
break;
}
} catch (ParseException ignore) {
}
}
} else if (java.util.Date.class == toType) {
Date check;
DateFormat[] dfs = getDateFormats(locale);
for (DateFormat df1 : dfs) {
try {
check = df1.parse(sa);
df = df1;
if (check != null) {
break;
}
} catch (ParseException ignore) {
}
}
}
//final fallback for dates without time
if (df == null) {
df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
}
try {
df.setLenient(false); // let's use strict parsing (XW-341)
result = df.parse(sa);
if (!(Date.class == toType)) {
try {
Constructor constructor = toType.getConstructor(new Class[]{long.class});
return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())});
} catch (Exception e) {
throw new TypeConversionException("Couldn't create class " + toType + " using default (long) constructor", e);
}
}
} catch (ParseException e) {
throw new TypeConversionException("Could not parse date", e);
}
} else if (Date.class.isAssignableFrom(value.getClass())) {
result = (Date) value;
}
return result;
}
private DateFormat[] getDateFormats(Locale locale) {
DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
DateFormat dt3 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
DateFormat d1 = DateFormat.getDateInstance(DateFormat.SHORT, locale);
DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale);
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd");
return new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
}
}