Developer Portal for YouTrack and Hub Help

Working with Dates and Times

Workflow rules often depend on dates and times. You can notify users before a due date, create follow-up dates, calculate how long an issue has been in progress, or stop an update when a work item is logged for the wrong day.

In JavaScript workflows, most date and time values are represented as Unix timestamps in milliseconds. This means that values returned by Date.now(), date and date-time custom fields, and issue properties such as created, updated, and resolved can be compared as numbers.

Date and Time Values

The following values are commonly used in workflow rules:

Value

Description

Date.now()

Returns the current Unix timestamp in milliseconds.

Issue properties

The created, updated, and resolved properties store timestamps. The resolved property is empty for unresolved issues.

Date custom fields

A custom field with the date type stores a timestamp for the selected calendar date. When a date is selected in YouTrack, the stored timestamp is normalized to 12:00 UTC for that date.

Date and time custom fields

A custom field with the date and time type stores the exact timestamp selected by the user or assigned by a workflow.

Period custom fields

A custom field with the period type stores a period value. Use the date-time module to create period values and the period object's methods to read its components.

Work item dates

Work item dates are also available as timestamps. You can compare them with Date.now() or normalize them with a JavaScript Date object.

Use the corresponding field type in rule requirements when your rule reads or writes custom fields:

requirements: { DueDate: { type: entities.Field.dateType, name: 'Due Date' }, Reminder: { type: entities.Field.dateTimeType, name: 'Reminder' }, Estimation: { type: entities.Field.periodType } }

Compare Dates

Because date and date-time values are timestamps, you can compare them with relational operators. Always check that optional values are present before you compare them.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); exports.rule = entities.Issue.onSchedule({ title: 'Find overdue issues', search: '#Unresolved has: {Due Date}', cron: '0 0 10 ? * MON-FRI', guard: (ctx) => { const dueDate = ctx.issue.fields.DueDate; return dueDate && dueDate < Date.now(); }, action: (ctx) => { ctx.issue.addComment('This issue is overdue.'); }, requirements: { DueDate: { type: entities.Field.dateType, name: 'Due Date' } } });

The following example checks whether a work item was added for a date more than one week in the past. Both values are normalized to the start of the UTC day before the comparison.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); const WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000; exports.rule = entities.Issue.onChange({ title: 'Reject old work items', guard: (ctx) => { return ctx.issue.workItems.added.isNotEmpty(); }, action: (ctx) => { const today = new Date().setUTCHours(0, 0, 0, 0); ctx.issue.workItems.added.forEach((item) => { const itemDate = new Date(item.date).setUTCHours(0, 0, 0, 0); workflow.check(itemDate >= today - WEEK_IN_MS, 'Adding work more than one week in the past is not allowed.'); }); }, requirements: {} });

Parse and Format Values

The workflow API includes the @jetbrains/youtrack-scripting-api/date-time module. Use this module when you need to parse user-provided text, format timestamps for messages or search queries, or calculate dates by adding or subtracting periods.

Use dateTime.parse() instead of the standard JavaScript Date.parse() method. The workflow method lets you pass one or more expected formats and an optional time zone.

const dateTime = require('@jetbrains/youtrack-scripting-api/date-time'); const start = dateTime.parse( '2026-05-15 09:00', 'yyyy-MM-dd HH:mm', 'Europe/Lisbon' );

Use dateTime.format() to create readable dates for messages or dates in a specific format for search queries.

const formatted = dateTime.format(ctx.issue.fields.DueDate, 'yyyy-MM-dd'); const withTimeZone = dateTime.format(Date.now(), 'yyyy-MM-dd HH:mm', 'America/New_York');

If you don't specify a format or time zone, YouTrack uses the values from the current user profile. For actions that are run by the workflow user, YouTrack uses the global date format and default time zone.

Add and Subtract Periods

Do not write expressions like Date.now() + 10 hours. JavaScript doesn't support period literals. Use numbers for fixed millisecond offsets or the date-time module for period-aware calculations.

For simple fixed intervals, define the interval in milliseconds:

const DAY_IN_MS = 24 * 60 * 60 * 1000; ctx.issue.fields.DueDate = Date.now() + 2 * DAY_IN_MS;

For intervals that should be represented as periods, use dateTime.after() and dateTime.before(). Duration strings use a compact format with weeks, days, hours, and minutes.

const dateTime = require('@jetbrains/youtrack-scripting-api/date-time'); const threeHoursFromNow = dateTime.after(Date.now(), '3h'); const twoDaysBeforeDueDate = dateTime.before(ctx.issue.fields.DueDate, '2d'); const fullPeriod = dateTime.after(Date.now(), '2w4d3h15m');

You can also pass a period value that was read from a period custom field or created with dateTime.toPeriod().

Work with Period Fields

Period fields store values as period objects. To assign a value to a period field, convert a number of milliseconds or a period string with dateTime.toPeriod().

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const dateTime = require('@jetbrains/youtrack-scripting-api/date-time'); exports.rule = entities.Issue.onChange({ title: 'Set default estimation', guard: (ctx) => { return ctx.issue.isReported && !ctx.issue.fields.Estimation; }, action: (ctx) => { ctx.issue.fields.Estimation = dateTime.toPeriod('1d4h'); }, requirements: { Estimation: { type: entities.Field.periodType } } });

When you need to calculate with a period value, read its components with methods like getWeeks(), getDays(), getHours(), and getMinutes(). The following helper converts a period value to minutes using the common default of five working days per week and eight working hours per day:

function periodToMinutes(period) { return period ? period.getMinutes() + 60 * (period.getHours() + 8 * (period.getDays() + 5 * period.getWeeks())) : 0; }

If your YouTrack instance uses different time tracking settings, adjust the conversion to match your working week and working day.

Calculate Working Time

Use Project.intervalToWorkingMinutes() when you want to calculate the number of minutes that fall within the project's working hours. This is the method used by the default work timer workflows.

const started = ctx.issue.fields.TimerTime; const duration = ctx.issue.project.intervalToWorkingMinutes(started, Date.now());

Use Issue.afterMinutes() when you need to add SLA-style business minutes to a starting timestamp. This method uses a calendar, such as the project's SLA calendar or the 24x7 calendar.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const calendar = ctx.issue.project.slaCalendar; ctx.issue.fields.FirstReply = ctx.issue.afterMinutes( ctx.issue.created, 60, calendar, true ); ctx.issue.fields.NextReply = ctx.issue.afterMinutes( Date.now(), 30, entities.Calendar24x7.instance(), false );

Tips

  • Use timestamps for direct comparisons and assignments to date or date-time fields.

  • Use dateTime.parse() when a date comes from text input or an external service.

  • Use dateTime.format() before adding dates to comments, notifications, or search queries.

  • Use dateTime.toPeriod() before assigning values to period fields.

  • Use Project.intervalToWorkingMinutes() for work timer calculations that must respect working hours.

  • Use Issue.afterMinutes() for SLA-style calculations that must respect a business-hours calendar.

11 May 2026