Share This Article
Working with dates and times is a fundamental aspect of building robust automation workflows. Whether you’re timestamping data, generating reports for specific periods, or scheduling tasks, getting the current moment accurately is crucial. In the world of workflow automation with n8n, you might initially think of standard JavaScript methods. However, n8n offers a much more powerful and reliable way to handle the current date and time directly within your expressions: the built-in $now
variable. Understanding how to leverage this feature can save you significant time and prevent frustrating inconsistencies, especially when dealing with different timezones and formatting requirements. This guide will walk you through everything you need to know about getting and manipulating the current time in your n8n workflows.
Why Current Time Matters in n8n Workflows
Before diving into the specifics, let’s appreciate why handling the current date and time effectively is so vital in automation. In n8n, the “now” timestamp serves numerous purposes:
- Data Timestamping: Recording exactly when an event occurred or when data was processed (e.g., adding a `created_at` or `updated_at` field to a database record).
- Dynamic File Naming: Generating unique filenames for reports, logs, or exports based on the current date and time (e.g., `sales_report_20231027_153000.csv`).
- Conditional Logic: Running specific workflow branches based on the time of day, day of the week, or date (e.g., sending a morning brief only on weekdays).
- Data Filtering: Selecting data within a specific time window relative to the present moment (e.g., fetching orders placed in the last 24 hours).
- Calculating Durations: Determining the time elapsed between an event and the current time.
- API Interactions: Providing current timestamps in required formats for specific API endpoints.
Given these diverse applications, using a reliable and flexible method for accessing and formatting the current time is non-negotiable for building dependable automations.
The Initial Approach: Native JavaScript Dates in n8n Expressions
n8n expressions {{ }}
allow you to execute JavaScript code. Therefore, your first instinct might be to use the standard JavaScript Date
object to get the current time. This is certainly possible:
1. Unix Timestamp (Milliseconds):
This gives you the number of milliseconds that have elapsed since the Unix epoch (January 1, 1970, at UTC).
{{ new Date().getTime() }}
Example Output: 1700500000123
2. ISO 8601 Format (UTC):
This is a standard, internationally recognized format. Using UTC (Coordinated Universal Time) is highly recommended for consistency, especially when dealing with servers or services in different locations.
{{ new Date().toISOString() }}
Example Output: 2023-11-20T17:06:40.123Z
(The ‘Z’ indicates UTC)
3. Human-Readable String (Local Timezone):
This provides a more readable string but includes the timezone offset of the server where n8n is running. This can sometimes be unpredictable.
{{ new Date().toString() }}
Example Output: Mon Nov 20 2023 12:06:40 GMT-0500 (Eastern Standard Time)
4. Locale-Specific Date String:
This attempts to format the date according to the server’s locale settings.
{{ new Date().toLocaleDateString() }}
Example Output: 11/20/2023
(Format depends heavily on server configuration)
5. Locale-Specific Formatting with Timezone (Attempt):
You might try to force a specific locale and timezone using options:
{{ new Date().toLocaleString("sv-SE", {timeZone: "Europe/Stockholm"}) }}
While this might seem like a solution for specific formatting and timezones, it leads us to a significant problem.
The Pitfall: Inconsistency with `toLocaleString`
The primary issue with relying heavily on methods like toLocaleString
(and to some extent, toString
and toLocaleDateString
) is the potential for major inconsistencies between different JavaScript environments. You might test an expression using your browser’s developer console and get one result, but when the n8n workflow runs on its server (using Node.js), the output could be entirely different.
This discrepancy often arises from:
- Underlying ICU Data: Node.js and browsers might use different versions or builds of the International Components for Unicode (ICU) library, which dictates localization behavior.
- Default Locale/Timezone: The server running n8n might have different default locale and timezone settings than your local machine or browser.
- Timezone Implementation: Full timezone support (like handling historical changes or complex rules for specific zones like “Asia/Tokyo”) within JavaScript’s native `Date` object, especially via `toLocaleString`, can be less robust or predictable than dedicated libraries.
Relying on these methods for critical formatting or timezone conversions can lead to subtle bugs that are hard to track down. Imagine generating reports for the wrong day or sending notifications at incorrect times due to unexpected timezone handling! This is why a more reliable approach is needed.
Alternative (But More Complex): The Function Node
For very complex date/time manipulations or if you were already heavily invested in libraries like Moment.js (though Luxon is now generally preferred for new projects due to its immutability and modern API), you could use the Function or Function Item node. Inside these nodes, you have a full Node.js environment where you can `require` external libraries.
// Inside a Function Nodeconst { DateTime } = require('luxon');const nowInTokyo = DateTime.now().setZone('Asia/Tokyo');item.tokyoTimeFormatted = nowInTokyo.toFormat('yyyy-MM-dd HH:mm:ss');return item;
While powerful, this approach requires writing more explicit code and managing dependencies (even though Luxon is often available). It adds complexity compared to using simple expressions for common tasks. For most standard “get current time and format it” scenarios, there’s a much simpler, built-in way.
The Modern n8n Solution: Enter `$now` and Luxon (Recommended)
Recognizing the need for robust and easy date/time handling, n8n includes the excellent Luxon library and makes it readily available within expressions via a special variable: $now
.
This is the recommended method for working with the current date and time in n8n expressions.
The $now
variable is essentially an instance of Luxon’s `DateTime` object, representing the exact moment the expression is evaluated. This gives you direct access to all of Luxon’s powerful and intuitive methods for formatting, manipulation, and timezone handling, without needing a Function node or worrying about native JavaScript inconsistencies.
Getting the Current Time with `$now`
At its simplest, you can just use `$now` itself, but its default string representation might not be what you need. More usefully:
Get Current Time (Luxon Object):
{{ $now }}
Output: Represents the Luxon DateTime object itself. Useful for chaining methods.
Get Current Time (ISO 8601 Format):
This is often the best starting point for consistency.
{{ $now.toISO() }}
Example Output: 2023-11-20T17:15:30.456Z
(Defaults to UTC, indicated by ‘Z’)
How to Use now() in n8n Expressions: Formatting Dates and Times
One of the biggest advantages of using `$now` is the ease of formatting. Luxon provides the .toFormat()
method, which accepts a string of tokens to define the output format.
{{ $now.toFormat('Your_Format_String') }}
Here are some common format tokens:
yyyy
: 4-digit year (e.g., 2023)yy
: 2-digit year (e.g., 23)MM
: 2-digit month (01-12)M
: 1 or 2-digit month (1-12)LLLL
: Full month name (e.g., November)LLL
: Abbreviated month name (e.g., Nov)dd
: 2-digit day of the month (01-31)d
: 1 or 2-digit day of the month (1-31)HH
: 2-digit hour, 24-hour format (00-23)H
: 1 or 2-digit hour, 24-hour format (0-23)hh
: 2-digit hour, 12-hour format (01-12)h
: 1 or 2-digit hour, 12-hour format (1-12)mm
: 2-digit minute (00-59)ss
: 2-digit second (00-59)SSS
: Milliseconds (000-999)a
: am/pmZZZZ
: Timezone offset name (e.g., Eastern Standard Time)ZZ
: Timezone offset (e.g., -05:00)ccc
: Abbreviated day of the week (e.g., Mon)cccc
: Full day of the week (e.g., Monday)
Examples:
- Get date like `YYYY-MM-DD`:
{{ $now.toFormat('yyyy-MM-dd') }}
Output: `2023-11-20`
- Get date and time like `DD/MM/YYYY HH:MM`:
{{ $now.toFormat('dd/MM/yyyy HH:mm') }}
Output: `20/11/2023 17:15` (Assumes UTC or server time initially)
- Get a friendly date format:
{{ $now.toFormat('cccc, LLLL d, yyyy') }}
Output: `Monday, November 20, 2023`
- Get time only (12-hour format):
{{ $now.toFormat('h:mm:ss a') }}
Output: `5:15:30 PM`
Handling Timezones Like a Pro with `$now`
This is where `$now` truly shines over native JavaScript in expressions. Luxon has excellent, built-in timezone support using the IANA Time Zone Database (e.g., ‘America/New_York’, ‘Europe/London’, ‘Asia/Kolkata’). You use the .setZone()
method before formatting.
Syntax:
{{ $now.setZone('Your/Timezone').toFormat('your_format_string') }}
Examples:
- Get the current time in New York (EST/EDT) and format it:
{{ $now.setZone('America/New_York').toFormat('yyyy-MM-dd HH:mm:ss') }}
Output: `2023-11-20 12:15:30` (Displays the local time in New York)
- Get the current time in Tokyo (JST) in ISO format with offset:
{{ $now.setZone('Asia/Tokyo').toISO() }}
Output: `2023-11-21T02:15:30.456+09:00` (Note the correct time and +09:00 offset)
- Get the date and friendly time in Paris (CET/CEST):
{{ $now.setZone('Europe/Paris').toFormat('dd-MMM-yyyy h:mm a ZZZZ') }}
Output: `20-Nov-2023 6:15 PM Central European Standard Time`
You can find a list of valid IANA timezone names on Wikipedia or other resources. Using the correct name is crucial.
.setZone()
correctly adjusts the displayed time according to the specified zone’s rules, including daylight saving time transitions. It doesn’t change the underlying instant in time, just how it’s represented.
Date/Time Manipulation with `$now`
Beyond just getting and formatting the current time, `$now` allows you to easily manipulate it using Luxon’s methods:
- Adding Time: Get tomorrow’s date.
{{ $now.plus({ days: 1 }).toFormat('yyyy-MM-dd') }}
Output: `2023-11-21`
- Subtracting Time: Get the ISO timestamp for 3 hours ago.
{{ $now.minus({ hours: 3 }).toISO() }}
Output: `2023-11-20T14:15:30.456Z`
- Setting Specific Units: Get the timestamp for the start of the current day (midnight).
{{ $now.startOf('day').toISO() }}
Output: `2023-11-20T00:00:00.000Z` (or relevant offset if zone is set)
- Setting Specific Values: Get today’s date but set the time to 9:00 AM.
{{ $now.set({ hour: 9, minute: 0, second: 0, millisecond: 0 }).toISO() }}
Output: `2023-11-20T09:00:00.000Z`
- Getting Parts of the Date/Time:
- Year:
{{ $now.year }}
-> `2023` - Month (1-12):
{{ $now.month }}
-> `11` - Day (1-31):
{{ $now.day }}
-> `20` - Weekday (1=Mon, 7=Sun):
{{ $now.weekday }}
-> `1` - Hour (0-23):
{{ $now.hour }}
-> `17`
- Year:
These manipulation capabilities make `$now` incredibly versatile for building dynamic date-based logic directly within your n8n expressions.
Related Reading
Native JS `new Date()` vs. `$now`: A Quick Comparison
Let’s briefly recap why `$now` is generally superior within n8n:
Native `new Date()`:
- Pros: Built into JavaScript, basic methods like `toISOString()` and `getTime()` are reliable.
- Cons: Formatting (`toLocaleString`, `toString`) is inconsistent across environments. Timezone handling is difficult and unreliable without external libraries. Manipulation requires manual calculations.
n8n `$now` (Luxon):
- Pros: Built into n8n expressions. Consistent and reliable formatting using `toFormat()`. Robust and easy timezone handling with `setZone()`. Powerful date/time manipulation methods (`plus`, `minus`, `startOf`, `set`, etc.). Immutable objects prevent accidental modification.
- Cons: Requires learning Luxon’s specific methods and format tokens (though they are quite intuitive).
For almost all use cases in n8n, the benefits of using `$now` far outweigh the minimal learning curve associated with Luxon.
A Note on Precision: Milliseconds vs. Microseconds/Nanoseconds
Standard JavaScript (and therefore Node.js, which powers n8n) primarily operates with millisecond precision via `Date.getTime()` or Luxon’s `toMillis()`. Achieving reliable microsecond or nanosecond precision directly is generally not feasible or consistent in these environments.
For most automation tasks, millisecond precision is more than sufficient. If you interact with a specific API that strictly requires a nanosecond timestamp format, the common (though technically imprecise) workaround is to take the millisecond timestamp and append six zeros.
Example (using native JS for simplicity here):
{{ new Date().getTime() + '000000' }}
Or with Luxon:
{{ $now.toMillis() + '000000' }}
Be aware that this doesn’t represent true nanosecond accuracy but fulfills the format requirement for some systems. Always check the API documentation carefully.
Practical Use Cases: `$now` in Action
Let’s solidify understanding with some concrete n8n scenarios:
1. Dynamically Naming a Daily Report File:
Imagine you need to save a CSV export every day, named with the date.
- Node: Write Binary File
- Parameter: File Name
- Expression:
report-{{ $now.toFormat('yyyyMMdd') }}.csv
- Result: A file named something like `report-20231120.csv`.
2. Adding a `processed_timestamp` to Airtable/Database:
When adding or updating records, you want to store when the n8n workflow processed them in UTC.
- Node: Airtable (or Postgres, MySQL, Set etc.)
- Parameter: Field Mapping (e.g., `Processed At` field)
- Expression:
{{ $now.toISO() }}
- Result: The field gets populated with the reliable ISO 8601 UTC timestamp, like `2023-11-20T17:15:30.456Z`.
3. Filtering Recent Items from an API Feed:
You fetch RSS feed items but only want to process those published in the last 6 hours.
- Node: IF Node
- Condition: Date & Time
- Value 1:
{{ $json.pubDate }}
(Assuming `pubDate` is an ISO string from the feed) - Operation: After
- Value 2:
{{ $now.minus({ hours: 6 }).toISO() }}
- Result: Only items published after the calculated time (6 hours ago) will pass through the TRUE branch.
4. Generating a Human-Readable Timestamp for Notifications:
Sending a Slack message and want to include when an event happened, displayed in the recipient’s timezone (e.g., Pacific Time).
- Node: Slack
- Parameter: Text
- Expression:
Alert! New order received at {{ $json.order_time.setZone('America/Los_Angeles').toFormat('h:mm a') }} PST.
(Assuming `order_time` holds an incoming ISO timestamp) - Result: A message like “Alert! New order received at 9:25 AM PST.”
These examples demonstrate how the flexibility of `$now` combined with Luxon methods allows for precise and context-aware date/time handling directly within your n8n nodes.
Troubleshooting Common Issues
Even with the power of `$now`, you might encounter occasional hiccups. Here are some common problems and how to fix them:
- Incorrect Format String: Using wrong tokens in `.toFormat()` (e.g., `YYYY` instead of `yyyy`, `MM` instead of `mm` for minutes). Double-check the Luxon documentation for the correct tokens.
- Invalid Timezone Name: Using an incorrect or misspelled timezone name in `.setZone()` (e.g., “America/NewYork” instead of “America/New_York”). Ensure you’re using valid IANA names.
- Expression Parsing Errors: Simple typos like missing curly braces `{{ }}`, incorrect method names (e.g., `toIso()` instead of `toISO()`), or syntax errors. Check the expression editor for error highlighting.
- UTC vs. Local Time Confusion: Remember that `$now.toISO()` usually defaults to UTC (‘Z’ suffix). If you need local time, you must use `.setZone()` first, then format (e.g., `{{ $now.setZone(‘Europe/Berlin’).toFormat(‘yyyy-MM-dd HH:mm:ss’) }}`). Formatting without setting a zone might implicitly use the server’s local time, which could be undesirable.
- Trying to Format Non-Luxon Dates: If you have a date string coming from another node (e.g., `$json.someDate`), you might need to parse it into a Luxon object first before you can format or manipulate it using Luxon methods. You’d typically do this in a Set node or Function node (`DateTime.fromISO($json.someDate)`). `$now` only works for the *current* time.
Conclusion: Mastering Time in Your n8n Workflows
Working with the current date and time is an essential skill for anyone building automations in n8n. While native JavaScript `Date` objects are available, they come with significant drawbacks regarding formatting consistency and timezone handling within the n8n environment.
The clear winner and recommended approach is leveraging the built-in $now
variable. Powered by the robust Luxon library, $now
provides an easy, consistent, and powerful way to:
- Get the current timestamp reliably.
- Format dates and times into virtually any required string format using
.toFormat()
. - Handle timezones accurately and effortlessly with
.setZone()
. - Perform date/time manipulations like adding, subtracting, or setting specific units.
By mastering How to Use now() in n8n Expressions, you eliminate a common source of errors and inconsistencies in your workflows. You gain the confidence that your timestamps, dynamic filenames, and time-based conditions will work exactly as expected, regardless of where your n8n instance is running.
Ready to build more powerful and reliable automations? Dive into your n8n workflows and start using the `$now` variable today. Explore the different formatting options and timezone settings to perfectly match your needs. If you haven’t explored the full potential of n8n yet, it’s a fantastic platform for connecting apps and automating tasks with or without code.