Jinja Templates in Workflows

Dynamic content generation with variables, expressions, and date/time operations

Jinja templates allow you to dynamically generate content in your workflows using variables, expressions, and built-in functions. This guide covers how to use Jinja templates, with a focus on date and time operations.

For simple, pre-formatted date and time values, you can use global variables like {{__exp_global.current_date}}. The datetime utilities described below provide more flexibility for custom formatting, timezone conversions, and calculations.

Basic Syntax

Jinja templates use double curly braces {{ }} for expressions and {% %} for control structures:

1{{ variable_name }}
2{{ workflow_state.some_field }}
3{{ "Hello " + user_name }}

For more information on accessing workflow state variables, see Workflow Logic & State > State Management.

Date and Time Operations

Available Utilities

The following datetime utilities are automatically available in all Jinja templates:

  • datetime - Python’s datetime class for creating and manipulating dates/times
  • timezone - For working with UTC timezone
  • ZoneInfo - For working with specific timezones (e.g., Pacific, Eastern)

Getting Current Time

Current UTC Time

1{{ datetime.now(timezone.utc) }}

Current Pacific Time

1{{ datetime.now(ZoneInfo("America/Los_Angeles")) }}

Other Common Timezones

1{{ datetime.now(ZoneInfo("America/New_York")) }} {# Eastern #}
2{{ datetime.now(ZoneInfo("America/Chicago")) }} {# Central #}
3{{ datetime.now(ZoneInfo("America/Denver")) }} {# Mountain #}
4{{ datetime.now(ZoneInfo("America/Anchorage")) }} {# Alaska #}
5{{ datetime.now(ZoneInfo("Pacific/Honolulu")) }} {# Hawaii #}

Formatting Dates and Times

Use the strftime() method to format datetime objects:

1{# Full date and time #}
2{{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%A, %B %d, %Y at %I:%M %p') }}
3{# Output: "Tuesday, March 02, 2024 at 10:30 AM" #}
4
5{# Date only #}
6{{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%Y-%m-%d') }}
7{# Output: "2024-03-02" #}
8
9{# Time only #}
10{{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%I:%M %p') }}
11{# Output: "10:30 AM" #}
12
13{# ISO format #}
14{{ datetime.now(timezone.utc).isoformat() }}
15{# Output: "2024-03-02T17:30:00+00:00" #}

Common strftime Format Codes

CodeDescriptionExample
%Y4-digit year2024
%mMonth (01-12)03
%dDay (01-31)02
%HHour (00-23)14
%IHour (01-12)02
%MMinute (00-59)30
%SSecond (00-59)45
%pAM/PMAM
%AFull weekday nameTuesday
%BFull month nameMarch
%bAbbreviated monthMar

Converting Between Timezones

Convert a UTC datetime to Pacific time:

1{{ datetime.now(timezone.utc).astimezone(ZoneInfo("America/Los_Angeles")) }}

Creating Specific Dates

Create a datetime for a specific date and time:

1{# March 15, 2024 at 10:30 AM Pacific #}
2{{ datetime(2024, 3, 15, 10, 30, 0, tzinfo=ZoneInfo("America/Los_Angeles")) }}
3
4{# Today at midnight UTC #}
5{{ datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) }}

Date Arithmetic

While Jinja doesn’t have built-in date arithmetic, you can work with timestamps:

1{# Get timestamp #}
2{{ datetime.now(timezone.utc).timestamp() }}
3
4{# Format relative time (requires custom logic or use of workflow state variables) #}

Common Use Cases

Including Current Date in Messages

1Today is {{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%A, %B %d, %Y') }}.
2
3The current time is {{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%I:%M %p') }}.

Generating Timestamps for Logs

1Log entry at {{ datetime.now(timezone.utc).isoformat() }}: {{ message }}

Time-Sensitive Conditional Logic

1{% set pacific_time = datetime.now(ZoneInfo("America/Los_Angeles")) %}
2{% set hour = pacific_time.hour %}
3{% if hour >= 9 and hour < 17 %}
4Business hours message
5{% else %}
6After hours message
7{% endif %}

Formatting Dates from Variables

If you have a date string in your workflow state, you can parse and format it:

1{# Assuming created_at is an ISO format string in your workflow state #}
2{{ datetime.fromisoformat(created_at).strftime('%B %d, %Y') }}

Available Variables

In addition to datetime utilities, your templates have access to:

  • Workflow State Variables: All variables from previous blocks in your workflow

    1{{ block_name.output }}
    2{{ user_input }}
  • Global Variables: Pre-formatted date/time strings (for convenience)

    1{{__exp_global.current_date}} {# "Tuesday, March 02, 2024" #}
    2{{__exp_global.current_time}} {# "10:30 AM" (local system time) #}
    3{{__exp_global.current_datetime}} {# "Tuesday, March 02, 2024 at 10:30 AM" #}
    4{{__exp_global.current_time_pacific}} {# "10:30 AM" #}
    5{{__exp_global.current_time_eastern}} {# "1:30 PM" #}
    6{{__exp_global.current_time_utc}} {# "5:30 PM" #}

For a complete list of global variables, see Workflow Logic & State > Global Variables.

  • Environment Variables: Access environment variables using _env
    1{{ _env.API_KEY }}

For more information, see Environment Variables.

Examples

Example 1: Email with Timestamp

1Subject: Report Generated - {{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%B %d, %Y') }}
2
3Your report was generated on {{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%A, %B %d, %Y at %I:%M %p %Z') }}.

Example 2: Dynamic Greeting Based on Time

1{% set pacific = datetime.now(ZoneInfo("America/Los_Angeles")) %}
2{% set hour = pacific.hour %}
3{% if hour < 12 %}
4Good morning!
5{% elif hour < 17 %}
6Good afternoon!
7{% else %}
8Good evening!
9{% endif %}

Example 3: ISO Timestamp for API Calls

1{
2 "timestamp": "{{ datetime.now(timezone.utc).isoformat() }}",
3 "message": "{{ user_message }}"
4}

Example 4: Combining with Workflow Variables

1Task completed by {{ user_name }} on {{ datetime.now(ZoneInfo("America/Los_Angeles")).strftime('%B %d, %Y at %I:%M %p') }}.
2
3Status: {{ task_status }}
4Notes: {{ task_notes }}

Tips and Best Practices

  1. Always specify timezones: When working with dates/times, explicitly specify the timezone to avoid ambiguity

    1{# Good #}
    2{{ datetime.now(ZoneInfo("America/Los_Angeles")) }}
    3
    4{# Avoid - no timezone #}
    5{{ datetime.now() }}
  2. Use UTC for storage/logging: Use UTC when storing timestamps or logging events

    1{{ datetime.now(timezone.utc).isoformat() }}
  3. Format for display: Use timezone-aware datetimes when displaying to users

    1{{ datetime.now(timezone.utc).astimezone(ZoneInfo("America/Los_Angeles")).strftime('%I:%M %p') }}
  4. Test your templates: Verify your date/time formatting works as expected in your workflow preview

  5. Choose the right tool: Use global variables for simple, pre-formatted dates. Use datetime utilities when you need custom formatting, timezone conversions, or calculations.

Additional Resources