FlowKit

The Date & Time node in n8n: format, calculate and compare dates without code

Published 4 August 2026 · 8 min read

Formatting a date as MM/DD/YYYY, scheduling a follow-up 7 days out, measuring how old a ticket is: these tasks show up in almost every workflow, and they too often end up as hand-rolled JavaScript expressions or baffling timezone offsets. n8n's Date & Time node covers exactly these cases without writing a line of code: it exposes the most common date operations through a visual interface, powered by the same Luxon library the expressions use behind the scenes. This guide walks through its operations with concrete examples, the timezone traps to watch for, and the cases where an expression or a Code node is still the better tool.

Date & Time node or Luxon expression: which one to pick?

n8n gives you two ways to manipulate dates, and they run on the same engine (Luxon):

  • the Date & Time node, a visible step in the canvas, configured through dropdowns;
  • Luxon expressions directly inside any node's field: {{ $now.setZone('America/New_York').toFormat('MM/dd/yyyy') }}.

The practical rule: if the date manipulation is a workflow step in its own right (computing a due date reused by several downstream nodes, normalizing dates across a batch of items), the node is more readable and easier for a non-developer colleague to maintain. If it's a detail of a single field (timestamping a file name, injecting today's date into a message), a one-line expression keeps the canvas lean. The full behavior of $now, $today and the Luxon methods is covered in our guide to dates and times with Luxon in n8n, and the general mechanics of {{ }} in our guide to n8n expression syntax.

A typical pipeline that combines both:

Webhook (ticket received) → Date & Time (Get Time Between Dates: ticket age)
      → IF (age > 48 h?) → Date & Time (Add to a Date: follow-up at D+7)
      → Set (format the fields) → Slack / Email

The node's operations, one by one

The Date & Time node offers a list of operations; here are the main ones, each with a real-world use case.

Format a Date — human-readable output

The most-used operation: it takes an input date (an item's field, an expression, or the current date) and returns it in the requested format. The predefined formats cover the standard cases, and a custom format accepts Luxon tokens:

Format Result
MM/dd/yyyy 08/04/2026
dd LLLL yyyy 04 August 2026
yyyy-MM-dd'T'HH:mm 2026-08-04T09:30
cccc Tuesday

Concrete case: a weekly report generated on Mondays, whose email subject should read "Report for 08/04/2026". A Date & Time node set to Format a Date, input {{ $now }}, format MM/dd/yyyy, and the output field slots straight into the send node's subject line.

Mind the token casing: in Luxon, mm means minutes and MM means month — swapping the two is the single most common formatting mistake.

Add/Subtract Time — the D+7 follow-up

The Add to a Date operation (and its twin, Subtract from a Date) adds or removes a duration: set the start date, the amount, and the unit (seconds through years). The classic case is the follow-up date: a quote sent today should trigger a reminder in 7 days.

The node computes followUpDate = sentDate + 7 days, and then you have two strategies: store that date in your CRM and let a scheduled workflow check it every morning, or have the workflow itself wait until the deadline with a Wait node in "Wait until specified time" mode pointing at the computed field — a pattern covered in detail in our guide to the Wait node.

Worth knowing: the addition works in calendar days. For business days, check the resulting weekday (weekday is 6 for Saturday, 7 for Sunday in Luxon) and shift accordingly — see the recipe at the end of this article.

Round a Date — snap to the start of the month or day

Round a Date rounds a date down or up to the chosen unit: start of the day, of the month, of the year… It's the operation to reach for when building clean period boundaries: "all orders since the start of the month" is just $now rounded down to the start of the month, with zero string wrangling.

Extract Part of a Date — route by month or hour

Extract Part of a Date isolates one component: year, month, day, hour, minute… Handy for conditional routing: a downstream IF or Switch node can route items by the extracted month (year-end closing tasks in December), or by the hour (an "urgent" queue for requests received outside business hours).

Get Current Date — the reference timestamp

Get Current Date inserts the current date-time into a field, with or without the time. It's the node equivalent of {{ $now }}, useful for timestamping a processing step ("imported on…") in a way that's visible in the canvas. If you're building an object with several fields including a timestamp, it's often simpler to group everything in a Set node with an expression — our guide to the Set / Edit Fields node shows how to combine static fields and expressions in a single step.

Get Time Between Dates — how old is that ticket

Get Time Between Dates computes the gap between two dates in the unit of your choice (minutes, hours, days…). Textbook example: measuring a support ticket's age between its creation date and now, to escalate anything past 48 hours:

Date & Time (Get Time Between Dates)
  Start Date : {{ $json.created_at }}
  End Date   : {{ $now }}
  Units      : hours
→ IF (timeDifference.hours > 48) → Slack escalation

The "Include Other Units" option returns the gap broken down (days + hours + minutes), handy for a human-friendly display ("open for 2 d 5 h").

Timezones: the three classic traps

Dates that are off "by exactly one or two hours" are the number-one symptom of a timezone problem, not a calculation bug. Three mechanisms stack up in n8n:

  1. GENERIC_TIMEZONE: the instance-level environment variable that sets the default timezone for all workflows. On an unconfigured self-hosted instance it's often UTC — hence timestamps that look "behind" local time by a few hours.
  2. The workflow's timezone: each workflow can override that default in its settings (Settings → Timezone). This is the timezone used by $now, $today and scheduled triggers — a detail that trips up plenty of Schedule Trigger users, as we cover in our guide to the Schedule Trigger, cron and timezones.
  3. ISO dates received from APIs: a string like 2026-08-04T07:30:00Z is in UTC (the trailing Z). If you format it as-is into a "time of day", you're displaying UTC time, not local time. It must be converted explicitly — via the timezone option in the Date & Time node, or .setZone('America/New_York') in Luxon — before any formatting.

The golden rule: store and pass dates around as ISO 8601 UTC throughout the workflow, and only convert to a local timezone at the very last moment, for display. Never fix an offset by manually adding a couple of hours: the workflow will break at the next daylight saving switch.

This care with timezones isn't perfectionism: in teams spread across time zones, temporal offset carries a well-documented coordination cost. A study by J. Alberto Espinosa and Erran Carmel published in 2003 in Software Process: Improvement and Practice lays the conceptual foundation for this phenomenon: time separation between members of a distributed team creates coordination costs of its own, distinct from mere geographic distance (Espinosa & Carmel, 2003 — see on Google Scholar). An automation that sends its notifications at the right local time for each recipient reduces exactly that kind of friction — provided the timezone handling is reliable.

When to prefer an expression or a Code node

The Date & Time node hits its limits in three situations:

  • Chained operations: "take the order date, add 3 days, round to the start of the day, format for display" would need three Date & Time nodes in a row. A Luxon expression does it in one line: {{ DateTime.fromISO($json.orderDate).plus({ days: 3 }).startOf('day').setZone('America/New_York').toFormat('MM/dd/yyyy') }}.
  • Conditional logic on the date: business days, public holidays, "the last Friday of the month"… As soon as there's an if in the reasoning, a Code node is clearer. Our guide to the Code node and JavaScript expressions covers accessing Luxon (DateTime) from the Code node.
  • Parsing exotic formats: a date received as 04-08-26 or Aug 4th, 2026 won't always be interpreted correctly. DateTime.fromFormat($json.date, 'dd-MM-yy') in Luxon removes the ambiguity explicitly.

Copy-paste recipes

Four expressions that cover the most frequent needs — paste them into a node field, or reproduce them with the equivalent Date & Time operations:

// Follow-up at D+7, at the start of the day, in ISO
{{ $now.plus({ days: 7 }).startOf('day').toISO() }}

// File timestamp: report-2026-08-04-0930.pdf
{{ 'report-' + $now.setZone('America/New_York').toFormat('yyyy-MM-dd-HHmm') + '.pdf' }}

// Ticket age in hours (whole number)
{{ Math.floor($now.diff(DateTime.fromISO($json.created_at), 'hours').hours) }}

// D+7 skipping the weekend (Saturday → Monday, Sunday → Monday)
{{ (() => { const d = $now.plus({ days: 7 }); return d.weekday === 6 ? d.plus({ days: 2 }) : d.weekday === 7 ? d.plus({ days: 1 }) : d; })().toISO() }}

Summary

The Date & Time node makes the six date manipulations that show up everywhere accessible without code: formatting, adding or subtracting time, rounding, extracting a component, timestamping, and measuring a gap. Reserve it for date steps that deserve to be visible in the canvas, switch to a Luxon expression when a single line is enough, and to a Code node as soon as the logic turns conditional. Above all, treat timezones as an explicit decision — workflow timezone verified, dates kept in UTC internally, local conversion only at display time — rather than an offset to patch: that's what separates a workflow that fires its follow-up at 9 a.m. local time all year round from one that drifts at every daylight saving change.

FAQ

Frequently asked questions

What's the difference between the Date & Time node and a Luxon expression in n8n?

Both rely on the same Luxon library under the hood. The Date & Time node exposes the common operations (format, add time, round, extract) through a no-code interface that's visible in the canvas; a Luxon expression ({{ $now.plus({ days: 7 }) }}) does the same thing in one line inside another node's field. Use the node when the date manipulation is a workflow step in its own right, and an expression when it's just a detail of a single field.

Why are my n8n dates off by a few hours?

It's almost always a timezone issue: n8n defaults to the timezone set by the GENERIC_TIMEZONE environment variable (or the workflow's own timezone in its settings), while ISO dates received from APIs are usually in UTC (the trailing Z). Check the workflow timezone in Settings, and convert explicitly with the Date & Time node's timezone option or .setZone() in Luxon rather than patching the offset by hand.

How do I add 7 days to a date in n8n without writing code?

Add a Date & Time node, pick the Add/Subtract Time operation (Add to a Date), point it at the input date field, enter 7 as the Duration and Days as the Time Unit. The node returns the new date in an output field you can name freely, ready for downstream nodes.

Does the Date & Time node handle business days?

No — the Add/Subtract Time operation counts calendar days, not business days. To skip weekends you need either a small expression that checks the resulting weekday ($now.plus({ days: 7 }).weekday) and shifts to Monday, or a Code node with a loop that increments while ignoring Saturday and Sunday.

Bundle FlowKit Complet

€269