back to blog

How to HubL: Add Dynamic Dates and Times to Automated Emails

12 min read • May 22, 2023

Showing the current day's date, providing coupon expiration information, announcing the end of a sale; there's a plethora of reasons to add dates to an email. However it can be tedious to update one such line for every email send and can be even more difficult to maintain when doing so in an automated email. To solve for this we can use HubL to write small snippets of code to create dynamic dates. A dynamic date will automatically update depending on the day the email is sent and/or based on other defined criteria. So let's get started:

local_dt and format_datetime

For dynamic dates there is a specific variable and function that you will need for just about any snippet you'll write. The variable local_dt outputs a datetime object of the current time in the time zone defined in your Account Defaults Settings. format_datetime (formally known as datetimeformat) is a function that will let us format that datetime object into something more readable. You can also use format_date or format_time if you're only interested in displaying one or the other.

The format functions have two required parameters—the datetime object you want to format and, of course, the format. There are four predefined formats you can use (short, medium, long, full) but you can also provide any custom format using Unicode Locale Data Markup Language. To show how the basics of this function works we'll start by outputting the simplest of dates, today's date, using the four predefined formats.

    
<strong>Short:</strong> {{ format_datetime(local_dt, "short") }}<br>
<strong>Medium:</strong> {{ format_datetime(local_dt, "medium") }}<br>
<strong>Long:</strong> {{ format_datetime(local_dt, "long") }}<br>
<strong>Full:</strong> {{ format_datetime(local_dt, "full") }}
Output
Short: 5/12/24 12:32 PM
Medium: May 12, 2024 12:32:24 PM
Long: May 12, 2024 12:32:24 PM Z
Full: Sunday, May 12, 2024 12:32:24 PM Z

It's important to note that, by default, format_datetime outputs the time in UTC (Coordinated Universal Time). You can use the two optional parameters, time zone and locale, to localize your date/time output.

Time zone allows you to dictate the time zone of the outputted time by providing a name from the IANA (Internet Assigned Numbers Authority) timezone database. You can also use the local_time_zone variable to use your HubSpot accounts time zone setting. The example below shows an output using my local_time_zone (America/Chicago) and Asia/Tokyo.

    
<strong>America/Chicago: </strong>{{ format_datetime(local_dt, "short", local_time_zone) }}<br>
<strong>Asia/Tokyo: </strong>{{ format_datetime(local_dt, "short", "Asia/Tokyo") }}<br>


  
Output
America/Chicago: 5/12/24 7:32 AM
Asia/Tokyo: 5/12/24 9:32 PM

Locale sets a specific locale to use. In the following example we'll change the locale to 'es' to change the language to Spanish.

    
{{ format_datetime(local_dt, "EEE, MMM d, yyyy", local_time_zone, "es") }}


  
Output
dom, may 12, 2024

plus_time and minus_time

Next let's dive into showing dates in the future and in the past. To do this we can use either of the two filters, plus_time and minus_time. Each of these filters has only two parameters—the amount you want to add/subtract and the unit you want to add/subtract by. There are 15 different units, but in email you're most likely to use days, weeks, months, and years. Below are a few examples using these filters. Note that the filter should be used on the time variable and not the whole function.

    
<strong>1 Week From Today: </strong>{{ format_datetime(local_dt|plus_time(1, 'weeks'), "EEE, MMM d, yyyy") }}<br>
<strong>2 Months From Today: </strong>{{ format_datetime(local_dt|plus_time(2, 'months'), "EEE, MMM d, yyyy") }}<br>
<strong>3 Days From Today: </strong>{{ format_datetime(local_dt|plus_time(3, 'days'), "EEE, MMM d, yyyy") }}<br>
<strong>4 Years Ago: </strong>{{ format_datetime(local_dt|minus_time(4, 'years'), "EEE, MMM d, yyyy") }}


  
Output
1 Week From Today: Sun, May 19, 2024
2 Months From Today: Fri, Jul 12, 2024
3 Days From Today: Wed, May 15, 2024
4 Years Ago: Tue, May 12, 2020

Advanced Dates

We've learned the basic variables, functions, and filters for writing dynamic dates so next is learning to use these in more advanced use cases. For instance, what if we only want to show business days and skip over weekends when outputting a date in the future? Or maybe instead of exactly two weeks ahead, we want to output twoThursdays ahead.

Business Days

To only output business days we'll start with creating a couple of variables: day_increase will default to how many days we originally want to go into the future by and date_weekday will get the weekday that the original increase falls on. We can use the EEEE unicode format to get the weekday.

    
{% set day_increase = 3 %}
{% set date_weekday = format_datetime(local_dt|plus_time(day_increase, 'days'), 'EEEE') %}


  

We'll then run an if else statement to check if date_weekday falls on a Saturday or Sunday. If it falls on a Saturday, we'll add 2 to our day_increase variable. If it falls on a Sunday we'll only add 1 to our day_increase variable.

    
{% if date_weekday == "Saturday" %}
  {% set day_increase = day_increase + 2 %}
{% elif date_weekday == "Sunday" %}
  {% set day_increase = day_increase + 1 %}
{% endif %}


  

Then we only need to output our date using day_increase as our amount variable for plus_time.

    
{% set day_increase = 3 %}
{% set date_weekday = format_datetime(local_dt|plus_time(day_increase, 'days'), 'EEEE') %}

{% if date_weekday == "Saturday" %}
  {% set day_increase = day_increase + 2 %}
{% elif date_weekday == "Sunday" %}
  {% set day_increase = day_increase + 1 %}
{% endif %}

{{ format_datetime(local_dt|plus_time(day_increase, 'days'), 'EEEE, MMM dd, yyyy') }}


  
Output
Wednesday, May 15, 2024

Weekday Specific

To get a specific weekday will involve just a little more footwork. We'll start it off by setting a few key variables: date will be our original future date, weekday will be the weekday that date lands on, and accepted_weekday will be the weekday we require our future date to land on.

    
{% set date = local_dt|plus_time(2, 'weeks') %}
{% set weekday = format_date(date, "EEEE") %}
{% set accepted_weekday = "Thursday" %}


  

Similar to looking for business days we'll then set up an in if else statement. If weekday is the same as accepted_weekday we'll go ahead and output our formatted date variable.

    
{% if weekday == accepted_weekday %}
  {{ format_date(date, "full") }}
{% else %}
  
{% endif %}


  

If weekday isn't the weekday we want though we'll then move into our else statement where we'll run through a for loop. Since are accepted weekday will be within the next 6 days we'll run the for loop through a range of 1 to 6 to find the nearest day from our date that matches our accepted_weekday. In the for loop we'll create a next_weekday variable to set the future weekday using from our loop. Then we'll check if next_weekday matches our accepted_weekday and, if it does, we'll output that day as our formatted date.

    
{% set date = local_dt|plus_time(2, 'weeks') %}
{% set weekday = format_date(date, "EEEE") %}
{% set accepted_weekday = "Thursday" %}

{% if weekday == accepted_weekday %}
  {{ format_date(date, "full") }}
{% else %}
  {% for x in range(1,7) %}
    {% set next_weekday = format_date(date|plus_time(x, 'days'), "EEEE") %}

    {% if next_weekday == accepted_weekday %}
      {{ format_date(date|plus_time(x, 'days'), "full") }}
    {% endif %}
  {% endfor %}
{% endif %}


  
Output
Thursday, May 30, 2024

And so the above will only ever show a Thursday date!

Add Your Dynamic Date to Your Email

Now at the end of all this you've learned you may be asking "now where do I put this code?" You have a couple of options actually. If you're just outputting a basic date with minimal code you can drop it right into the text of your email. It'll show up as code in the email editor, but in the email preview and sent emails it'll show the rendered date.

formatted datetime in drag-and-drop email richtext

For more complex code, like mentioned in the advanced section, it may be more intuitive to create a custom module in the Design Manager. You can create a module specifically just to house your dynamic date code or code out the entire section you're using the date in. Also, if you're building a custom coded template, instead of using HubSpot's drag-and-drop email, you can place the code directly in the template. Putting your code in a module or template will render it in the email editor exactly as it'll appear in the email.

dynamic date module in drag-and-drop email

programmable email module toggle

Formatting Personalization Tokens

In some use cases you may want to output a date from a contact's data in HubSpot. However, it's not possible to use filters and functions on personalization tokens in basic emails. You would need to have a subscription tier that includes the programmable emails beta to be able to mutate personalization tokens. If you do have the programmable emails beta—you won't be able to mutate tokens directly in the email, but you can make email modules with this capability by flipping on the programmable email switch.

 

With the help of dynamic dates you can now more easily set and forget your automated emails or even save time when manually sending emails from a template with predefined content. 

Discussion