date, time, datetime (when used with a date/time/date-time value)
These built-ins can be used to specify which parts of the date-like variable are in use:
-
date
: Date only, no time of the day. -
time
: Only the time of the day, no date part -
datetime
: Both date and time
Ideally, you do not need to use these built-ins.
Unfortunately, because of the technical limitations of the Java
platform, FreeMarker sometimes can't find out which parts of a
date-like value is a date, a time or a date-time; ask the
programmers which variables has this problem. If FreeMarker has to
execute an operation where this information is needed -- such as
displaying the value as text -- but it does not know which parts are
in use, it will stop with error. This is when you have to use these
built-ins. For example, assume openingTime
is a
such problematic variable:
<#assign x = openingTime> <#-- no problem can occur here --> ${openingTime?time} <#-- without ?time it would fail --> <#-- For the sake of better understanding, consider this: --> <#assign openingTime = openingTime?time> ${openingTime} <#-- this will work now -->
These built-ins can also be used to convert date-time values to date or time. For example:
Last updated: ${lastUpdated} <#-- assume that lastUpdated is a date-time value --> Last updated date: ${lastUpdated?date} Last updated time: ${lastUpdated?time}
will output something like:
Last updated: 04/25/2003 08:00:54 PM Last updated date: 04/25/2003 Last updated time: 08:00:54 PM
If the left side of the ?
is string, then
these built-ins convert
strings to date/time/date-time.
date_if_unknown, time_if_unknown, datetime_if_unknown
This built-in exists since FreeMarker 2.3.21.
The date_if_unknown
,
time_if_unknown
,
datetime_if_unknown
built-ins mark a date-like
value with some of the sub-types: date without time, time, or
date-time, respectively. However, if the value already holds this
information, the built-in has no effect. That is, it will never
convert the sub-type of a value, it only adds the sub-type if it was
unknown.
iso_...
These built-ins are deprecated since
FreeMarker 2.3.21, where the date_format
,
time_format
and
datetime_format
settings understand
"iso"
(for ISO 8601:2004 format) and
"xs"
(for XML Schema format) in additionally to
the Java SimpleDateFormat
patterns. Thus the
default format can be set to ISO 8601, or for one time ISO
formatting you can use myDate?string.iso
. See more
here...
These built-ins convert a date, time or date-time value to string that follows ISO 8601:2004 "extended" format.
This built-in has several variations:
iso_utc
, iso_local
,
iso_utc_nz
, iso_local_nz
,
iso_utc_m
, iso_utc_m_nz
, etc.
The name is constructed from the following words in this order, each
separated with a _
from the next:
-
iso
(required) -
Either
utc
orlocal
(required (except when it's given with a parameter, but see that later)): Specifies whether you want to print the date/time/date-time according to UTC or according the current time zone. The current time zone is decided by thetime_zone
FreeMarker setting and is normally configured by the programmers outside the templates (but it can also be set in a template, like<#setting time_zone="America/New_York">
for example). Note that if thesql_date_and_time_time_zone
FreeMarker setting is set and non-null
, then forjava.sql.Date
andjava.sql.Time
values (i.e., for date-only and time-only values that are coming from database via SQL)local
will mean that time zone instead of the value of thetime_zone
setting. -
Either
h
orm
orms
(optional): The accuracy of the time part. When omitted, it defaults to seconds accuracy (like12:30:18
).h
means hours accuracy (like12
),m
means minutes accuracy (12:30
), andms
means milliseconds accuracy (12:30:18.25
, where we have 250 ms). Note that when usingms
, the milliseconds are displayed as fraction seconds (following the standard) and will not have trailing0
-s. Thus, if the the millisecond part happens to be0
, the whole fraction second part will be omitted. Also note that the fraction seconds are always separated with a dot , not with comma (to follow the Web conventions and XML Schema time/dateTime canonical format). -
nz
(optional):nz
(like in${foo?utc_local_nz}
) stands for "no zone", which means that the time zone offset (like+02:00
or or-04:30
orZ
) will not be displayed. If this part is omitted (like in${foo?utc_local}
) the zone will be displayed, except in two cases:-
If the value is a date (no time part) value (again, ISO 8901 doesn't allow it then)
-
If the value is a
java.sql.Time
and theincompatible_improvements
(often set via the JavaConfiguration
constructor parameter) FreeMarker configuration setting is at least 2.3.21 (or 2.3.24 when you are inside a string literal). This is because most databases store time values that aren't in any time zone, but just store hour, minute, second, and decimal second field values, so showing the time zone doesn't make sense.
Note that since FreeMarker 2.3.19, the offset always contains the minutes for XML Schema date/time/dateTime format compliance. (However, if you primarily generate for the XML Schema format, use the xs format.)
-
Example:
<#assign aDateTime = .now> <#assign aDate = aDateTime?date> <#assign aTime = aDateTime?time> Basic formats: ${aDate?iso_utc} ${aTime?iso_utc} ${aDateTime?iso_utc} Different accuracies: ${aTime?iso_utc_ms} ${aDateTime?iso_utc_m} Local time zone: ${aDateTime?iso_local}
A possible output (depends on current time and time zone):
Basic formats: 2011-05-16 21:32:13Z 2011-05-16T21:32:13Z Different accuracies: 21:32:13.868Z 2011-05-16T21:32Z Local time zone: 2011-05-16T23:32:13+02:00
There is yet another group of iso_...
built-in variants, where you omit the local
or
utc
word from the name and instead specify the
time zone as a parameter to the built-in. Example:
<#assign aDateTime = .now> ${aDateTime?iso("UTC")} ${aDateTime?iso("GMT-02:30")} ${aDateTime?iso("Europe/Rome")} The usual variations are supported: ${aDateTime?iso_m("GMT+02")} ${aDateTime?iso_m_nz("GMT+02")} ${aDateTime?iso_nz("GMT+02")}
A possible output (depends on current time and time zone):
2011-05-16T21:43:58Z 2011-05-16T19:13:58-02:30 2011-05-16T23:43:58+02:00 The usual variations are supported: 2011-05-16T23:43+02:00 2011-05-16T23:43 2011-05-16T23:43:58
If the time zone parameter can't be interpreted, the template processing will be terminated with error.
The parameter can be a
java.util.TimeZone
object too (which is possibly
the return value of a Java method, or it's in the data-model), not
just a string.
string (when used with a date/time/date-time value)
This built-in converts a date to a string, with the specified formatting.
You should need this built-in rarely, as the default format
of date/time/date-time values can be specified globally with the
date_format
, time_format
and
datetime_format
settings of FreeMarker.
Use this built-in only at the places where the desired format
differs from the one normally used. For the other places the
default format should be set properly by the programmers, outside
the templates.
The desired format can be specified like
?string.format
or
?string["format"]
(or
the historical equivalent,
?string("format")
).
These are equivalent, except that with the quoted formats you can
include any characters in the
format
, like spaces.
The syntax of format
is exactly the same as of the date_format
,
time_format
and
datetime_format
configuration settings; see the documentation of the
possible values there.
Example: If the locale of the output is U.S. English, and the
time zone is the U.S. Pacific Time zone, and
openingTime
is a
java.sql.Time
, nextDiscountDay
is java.sql.Date
and
lastUpdated
is
java.sql.Timestamp
or
java.util.Date
then this:
<#-- Predefined format names: --> ${openingTime?string.short} ${openingTime?string.medium} ${openingTime?string.long} ${openingTime?string.full} ${openingTime?string.xs} <#-- XSD xs:time --> ${openingTime?string.iso} <#-- ISO 8601 time --> ${nextDiscountDay?string.short} ${nextDiscountDay?string.medium} ${nextDiscountDay?string.long} ${nextDiscountDay?string.full} ${nextDiscountDay?string.xs} <#-- XSD xs:date --> ${nextDiscountDay?string.iso} <#-- ISO 8601 date --> ${lastUpdated?string.short} ${lastUpdated?string.medium} ${lastUpdated?string.long} ${lastUpdated?string.full} ${lastUpdated?string.medium_short} <#-- medium date, short time --> ${lastUpdated?string.xs} <#-- XSD xs:dateTime --> ${lastUpdated?string.iso} <#-- ISO 8601 combined date and time --> <#-- Programmer-defined named format (@ + name): --> ${lastUpdated?string.@fileDate} <#-- Advanced ISO 8601 and XSD formatting: --> ${lastUpdated?string.iso_m_u} ${lastUpdated?string.xs_ms_nz} <#-- SimpleDateFormat patterns: --> ${lastUpdated?string["dd.MM.yyyy, HH:mm"]} ${lastUpdated?string["EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'"]} ${lastUpdated?string["EEE, MMM d, ''yy"]} ${lastUpdated?string.yyyy} <#-- Same as ${lastUpdated?string["yyyy"]} -->
will print something like this:
01:45 PM 01:45:09 PM 01:45:09 PM PST 01:45:09 PM PST 13:45:09-08:00 13:45:09-08:00 2/20/07 Apr 20, 2007 April 20, 2007 Friday, April 20, 2007 2007-02-20-08:00 2007-02-20 2/20/07 01:45 PM Feb 20, 2007 01:45:09 PM February 20, 2007 01:45:09 PM PST Friday, February 20, 2007 01:45:09 PM PST Feb 8, 2003 9:24 PM 2007-02-20T13:45:09-08:00 2007-02-20T13:45:09-08:00 Apr/20/2007 13:45 2007-02-20T21:45Z 2007-02-20T13:45:09.000 08.04.2003 21:24 Tuesday, April 08, 2003, 09:24 PM (PDT) Tue, Apr 8, '03 2003
Note that with custom formats like in
lastUpdated?string.@fileDate
above, templates can
just refer to the application-domain meaning, and the exact format
can be specified outside the templates, on a central place.
(Programmers can read about defining such named formats
here...)
Unfortunately, because of the limitations of the Java
platform, it can happen that you have date-like variables in the
data-model, where FreeMarker can't decide if the variable is a
date (year, month, day), or a time (hour, minute, second,
millisecond) or a date-time. In this case, FreeMarker doesn't know
how to display the value when you write something like
${lastUpdated?string.short}
or
${lastUpdated?string.xs}
, i.e., a format that
doesn't specify the exact fields to display, or if you simply use
${lastUpdated}
. Then it will have to stop with
error. To prevent this, you can help FreeMarker with the ?date
,
?time
and ?datetime
built-ins. For example:
${lastUpdated?datetime?string.short}
. Ask the
programmers if certain variables of the data-model have this
problem, or always use ?date
,
?time
and ?datetime
built-ins to be on the safe side.
You never need to use ?date
,
?time
or ?datetime
with
format patterns like "yyyy.MM.dd HH:mm"
, since
with the pattern you tell FreeMarker what parts of the date to
show. However, FreeMarker will trust you blindly, so you can show
"noise" if you display parts that are actually not stored in the
variable. For example, ${openingTime?string["yyyy-MM-dd
hh:mm:ss a"]}
, where openingTime
stores only time, will display 1970-01-01 09:24:44
PM
.
To prevent misunderstandings, the format need not be a string
literal, it can be a variable or any other expression as far as it
evaluates to a string. For example, it can be like
"..."?string[myFormat]
.
See also: the interpolation of dates