【发布时间】:2011-03-09 20:19:59
【问题描述】:
有没有办法在 Freemarker 中轻松格式化 Joda DateTime 对象?例如对于 Java 日期,我们可以使用 ?string 和其他指令。
我知道我可以调用 toDate 并获取 Java 日期,但我希望有更好的方法。
【问题讨论】:
标签: datetime freemarker jodatime
有没有办法在 Freemarker 中轻松格式化 Joda DateTime 对象?例如对于 Java 日期,我们可以使用 ?string 和其他指令。
我知道我可以调用 toDate 并获取 Java 日期,但我希望有更好的方法。
【问题讨论】:
标签: datetime freemarker jodatime
您应该可以直接从 Freemarker 调用 toString(String pattern) 方法:
${dateTime.toString('MM-dd-yy')}
(未测试)
【讨论】:
如果您不想在模板上到处乱写toString('MM-dd-yy'),还有一种更简单的方法。
只需扩展 Freemarker 的 DefaultObjectWrapper,让它开箱即用地理解 Joda Time:
public class JodaAwareObjectWrapper extends DefaultObjectWrapper {
@Override
public TemplateModel wrap(final Object obj) throws TemplateModelException {
if (obj == null) { return super.wrap(obj); }
if (obj instanceof LocalDate) { return new SimpleDate(((LocalDate) obj).toDate(), TemplateDateModel.DATE); }
// add support for all desired types here...
return super.wrap(obj);
}
}
并在启动 FreeMarker 引擎时将此对象包装器提供给 FreeMarker 配置
Configuration config = // ...
config.setObjectWrapper(new JodaAwareObjectWrapper());
然后您可以在模板中使用 FreeMarkers 标准日期内置插件,例如 ${dateTime?date}
【讨论】:
if (obj instanceof LocalDate) { return super.wrap(((LocalDate)obj).toDate()); }。另外,if (obj == null) {...} 行是多余的。
我不相信此时 Freemarker 中没有任何针对 JodaTime 的集成。将对象放入模型中进行格式化非常容易,即
使用 format(String pattern, DateTime dateTime) 方法编写一个类“MyCustomJodaFormatterBean”。将 this 的一个实例放在根目录中。
root.put("joda", 新 MyCustomJodaFormatterBean());
然后在freemarker中,
${joda.format("MM-dd-yyy", dateTime)}
【讨论】:
在解析 FTL 文件期间,freemarker 会构建其内部对象模型。例如 java.util.Date 表达式被包装到 freemarker.template.SimpleDate 中。如果您的模型的表达式值是 org.joda.time.DateTime 类型 - freemarker 未知,它将默认包装到 freemarker.ext.beans.StringModel 中,将您的 DateTime 转换为字符串使用 toString() 方法。
例如,假设我们在 FTL 表达式中有:
med.expiryDate?date <= today?date
其中“med.expiryDate”是日期时间类型。 "med.expiryDate" 将被包装到 freemarker.ext.beans.StringModel 中,然后使用 freemarker.template.Configuration dateFormat 解析 "med.expiryDate?date"。如果此 dateFormat 与 DateTime.toString() 的默认格式不同,则可能导致异常。
要解决此问题,您需要让 Freemarker 了解 DateTime 也是日期,而不是字符串。编写您的自定义对象包装器:
/**
* Wrapper to make freemarker identify org.joda.time.DateTime objects as date.
* User: evvo
* Date: 5/26/2016
* Time: 18:21
*/
public class DateTimeAwareObjectWrapper extends DefaultObjectWrapper {
@Override
public TemplateModel wrap(Object obj) throws TemplateModelException {
if (obj instanceof DateTime) {
return new SimpleDate(((DateTime) obj).toDate(), getDefaultDateType());
}
return super.wrap(obj);
}
}
并将其设置到 freemarker 配置中
configuration.setObjectWrapper(new DateTimeAwareObjectWrapper());
经过这样的更改,我相信 ?string 后缀也将适用于 DateTime 表达式。
【讨论】: