Built-ins for date/time/date-time values
Page Contents
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:
| |||
These built-ins can also be used to convert date-time values to date or time. For example:
| |||
will output something like:
| |||
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
Note
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_...
Note
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 or local (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 the time_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 the sql_date_and_time_time_zone FreeMarker setting is set and non-null, then for java.sql.Date and java.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 the time_zone setting.
-
Either h or m or ms (optional): The accuracy of the time part. When omitted, it defaults to seconds accuracy (like 12:30:18). h means hours accuracy (like 12), m means minutes accuracy (12:30), and ms means milliseconds accuracy (12:30:18.25, where we have 250 ms). Note that when using ms, the milliseconds are displayed as fraction seconds (following the standard) and will not have trailing 0-s. Thus, if the the millisecond part happens to be 0, 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 or Z) 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 the incompatible_improvements (often set via the Java Configuration constructor parameter) FreeMarker configuration setting is at least 2.3.21. 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:
| |||
A possible output (depends on current time and time zone):
| |||
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:
| |||
A possible output (depends on current time and time zone):
| |||
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.
Note
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:
| |||
will print something like this:
| |||
Warning!
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.
Note
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, like in "..."?string[myFormat].
See also: the interpolation of dates