ResourcesKnowledge Base

Using date & time functions

One of the most common needs in templates is manipulation of date and time. While you may think that all you need is to add and subtract dates, there are many other scenarios that make sense and can take advantage of date & time calculations.

As with many other advanced features, the date & time functions are provided via a plugin that needs to be loaded first:

[% USE date -%]

The plugin provides the format() method which accepts a time value, a format string and a locale name. All of these parameters are optional with the current system time, default format ('%H:%M:%S %d-%b-%Y') and en_US locale being used respectively, if undefined. Default values for the time, format and/or locale may be specified as named parameters in the USE directive.

[% USE date(format='%-d.%-m.%Y') %]

This would set the formating to the european standard d.m.y format with no leading zeros, eg. 1.2.2020. See below for standard placeholders.

Now that we have loaded the date & time plugin we can start working with the values of date & time. The very basic would be to return the current date & time according to the default formating:

[% date.format -%]

Keep in mind that current date & time applies to time of display. In that sence using a current date & time in an email will represent the date & time of the email being generated. If the email contains a link to display in browser that preview in browser will feature the current date & time at the time of display not the time the email was sent.

You can use the function to format any date & time value to your format by passing a specific date in the parameter date.format(date_value). As such it can be use to format the date & time of email being sent (see content variables):

[% senddate = '' _ email.YEAR _ '-' _ email.MONTH _ '-' _ email.DAY _ ' ' _ '00:00:00' -%]
[% date.format(senddate) -%]

Another simple example would be pulling a date of last order stored in recipient’s CUSTOM1 field and manipulating that date (asuming full timestamp is stored):

[% date.format(recipient.CUSTOM1) -%]

In case the field only contains the date and no time we simply add an arbitrary time to the value by appending _ ‘00:00:00’ to the value.
The date plugin also has some more enhanced feature that allow for manipulation and calculations of date & time and those could be passed as values for formating. The output from more complex calculation, for example a formatted value of an upcoming date 7 days from today would be following:

[% date.format(date.manip.UnixDate("7 days later","%s")) %]

Or you could also override the default and return the date in a format of your choice for that specific output. In this case we want to return the date of the day 60 days before today in a US format while the default format is set to european:

[% date.format(date.manip.UnixDate("60 days earlier","%s"), '%d.%-m.%Y %-I:%M %p') %]

As you may have noticed there is a new function in the above calls called manip related to a plugin called Date::Manip. It provides a large range of date/time manipulation functions that can further extend the level of your automation in the templates. As if that was not enough there is another nice plugin called Date::Calc which provides additional calendar calculations. 

[% date.format(date.calc.Easter_Sunday(year).join('/') _ ' 00:00:00') %]

Did you ever wanted to include the date of Easter sunday in your templates without having to update the date every year? This is the line that will do the trick and combined with other date and time manipulations you can easily add a Easter block to your template that will only show up 2 weeks before and up until Easter sunday. That will require 2 different calculations - one to get the date of easter:

[% easter = date.format(date.calc.Easter_Sunday(year).join('/') _ ' 00:00:00','%s') %]

And the date 20 day prior:

[% pre_easter = date.manip.UnixDate(date.manip.DateCalc("20 days earlier", date.calc.Easter_Sunday(year).join('/')),'%s') %]

Now that we have these 2 numbers as UnixDate value which is a time in seconds since epoch we can create a simple condition to show some content:

[% IF date.now > pre_easter && date.now < easter -%]
   <h1>Easter is coming!</h1>
[% END -%]

If we want to take it a step further, we can also calculate the number of days left till easter and have an even cooler message. To calculate the remaining days we will use the delta function to see the difference between current date and calculated easter:

[% daystogo =  date.calc.Delta_Days(date.format(date.now,'%Y'),date.format(date.now,'%m'),date.format(date.now,'%d'),date.format(easter,'%Y'),date.format(easter,'%m'),date.format(easter,'%d')) -%]

And use that value within our final block:

[% easter = date.format(date.calc.Easter_Sunday(year).join('/') _ ' 00:00:00','%s') %]
[% pre_easter = date.manip.UnixDate(date.manip.DateCalc("20 days earlier", date.calc.Easter_Sunday(year).join('/')),'%s') %]
[% daystogo =  date.calc.Delta_Days(date.format(date.now,'%Y'),date.format(date.now,'%m'),date.format(date.now,'%d'),date.format(easter,'%Y'),date.format(easter,'%m'),date.format(easter,'%d')) -%]
[% IF date.now > pre_easter && date.now < easter -%]
   <h1>Easter is coming in [% daystogo -%] days!</h1>
[% END -%]

Obviously this would be considerably easier for christmas since the date is fixed but we may want to adjust the content based on what day the christmas will be at. The very same math could be used for any other occasion for example an automated birthday gift coupon, spouse’s birthday reminder, wedding anniversary, etc. The limits of its use are endless.

Standard date & time formatting placeholders:

%a The abbreviated name of the day of the week according to the en_US locale.  (Calculated from tm_wday.)
%A The full name of the day of the week according to the en_US locale.  (Calculated from tm_wday.)
%b The abbreviated month name according to the en_US locale. (Calculated from tm_mon.)
%B The full month name according to the en_US locale. (Calculated from tm_mon.)
%c The preferred date and time representation for the current locale.
%C The century number (year/100) as a 2-digit integer. (SU) (Calculated from tm_year.)
%d The day of the month as a decimal number (range 01 to 31). To return the value without the leading zero a %-d formatting should be used. (Calculated from tm_mday.)
%D Equivalent to %m/%d/%y. (American date format. Americans should note that in other countries %d/%m/%y is rather common. This means that in an international context this format is ambiguous and should not be used.) (SU)
%e Like %d, the day of the month as a decimal number, but a leading zero is replaced by a space. (SU) (Calculated from tm_mday.)
%F Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)
%G The ISO 8601 week-based year (see NOTES) with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V). This has the same format and value as %Y, except that if the ISO week number belongs to the previous or next year, that year is used instead. (TZ) (Calculated from tm_year, tm_yday, and tm_wday.)
%g Like %G, but without century, that is, with a 2-digit year (00–99). (TZ) (Calculated from tm_year, tm_yday, and tm_wday.)
%h Equivalent to %b. (SU)
%H The hour as a decimal number using a 24-hour clock (range 00 to 23). To return the value without the leading zero a %-H formatting should be used. (Calculated from tm_hour.)
%I The hour as a decimal number using a 12-hour clock (range 01 to 12). To return the value without the leading zero a %-I formatting should be used. (Calculated from tm_hour.)
%j The day of the year as a decimal number (range 001 to 366). (Calculated from tm_yday.)
%k The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded by a blank.  (See also %H.) (Calculated from tm_hour.)  (TZ)
%l The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded by a blank. (See also %I.) (Calculated from tm_hour.)  (TZ)
%m The month as a decimal number (range 01 to 12). To return the value without the leading zero a %-m formatting should be used. (Calculated from tm_mon.)
%M The minute as a decimal number (range 00 to 59). To return the value without the leading zero a %-M formatting should be used. (Calculated from tm_min.)
%n A newline character. (SU)
%p Either "AM" or "PM" according to the given time value, or the corresponding strings for the current locale.  Noon is treated as "PM" and midnight as "AM".  (Calculated from tm_hour.)
%P Like %p but in lowercase: "am" or "pm" or a corresponding string for the current locale.  (Calculated from tm_hour.) (GNU)
%r The time in a.m. or p.m. notation.  In the POSIX locale this is equivalent to %I:%M:%S %p.  (SU)
%R The time in 24-hour notation (%H:%M). (SU) For a version including the seconds, see %T below.
%s The number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). (TZ) (Calculated from mktime(tm).)
%S The second as a decimal number (range 00 to 60). To return the value without the leading zero a %-S formatting should be used. (The range is up to 60 to allow for occasional leap seconds.) (Calculated from tm_sec.)
%t A tab character. (SU)
%T The time in 24-hour notation (%H:%M:%S).  (SU)
%u The day of the week as a decimal, range 1 to 7, Monday being 1.  See also %w.  (Calculated from tm_wday.)  (SU)
%U The week number of the current year as a decimal number, range 00 to 53, starting with the first Sunday as the first day of week 01. To return the value without the leading zero a %-U formatting should be used. See also %V and %W.  (Calculated from tm_yday and tm_wday.)
%V The ISO 8601 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the new year. To return the value without the leading zero a %-V formatting should be used. See also %U and %W. (Calculated from tm_year, tm_yday, and tm_wday.)  (SU)
%w The day of the week as a decimal, range 0 to 6, Sunday being 0. See also %u.  (Calculated from tm_wday.)
%W The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01. To return the value without the leading zero a %-W formatting should be used. (Calculated from tm_yday and tm_wday.)
%x The preferred date representation for the current locale without the time.
%X The preferred time representation for the current locale without the date.
%y The year as a decimal number without a century (range 00 to 99). (Calculated from tm_year)
%Y The year as a decimal number including the century. (Calculated from tm_year)
%Z The timezone name or abbreviation.