Date.UTC()
Build a timestamp from calendar components interpreted as UTC rather than local time.
Date.UTC(year)
Date.UTC(year, monthIndex)
Date.UTC(year, monthIndex, day)
Date.UTC(year, monthIndex, day, hours)
Date.UTC(year, monthIndex, day, hours, minutes)
Date.UTC(year, monthIndex, day, hours, minutes, seconds)
Date.UTC(year, monthIndex, day, hours, minutes, seconds, milliseconds)- Added in JavaScript ES1
Parameters
| Parameter | Type | Description |
|---|---|---|
$year | number | The year. Integers 0 to 99 are converted to 1900 + year, so 95 means 1995; all other values are the literal year. |
$monthIndexoptional | number= 0 | The month as a zero-based index, 0 for January through 11 for December. |
$dayoptional | number= 1 | The day of the month. |
$hoursoptional | number= 0 | The hour of the day, 0 to 23. |
$minutesoptional | number= 0 | The minutes past the hour. |
$secondsoptional | number= 0 | The seconds past the minute. |
$millisecondsoptional | number= 0 | The milliseconds past the second. |
Return value
numberA number: the timestamp in milliseconds since 1 January 1970 UTC for the supplied components, read as UTC. Returns NaN if any argument coerces to NaN or the result is out of range.
Errors
Never throws — invalid or out-of-range components yield NaN.
Changelog
- PHP ES2017Calling Date.UTC() with a single argument is required to treat the omitted monthIndex as 0. Older engines returned NaN, so Date.UTC(2017) was unusable before this change.
Date.UTC() is the counterpart to the multi-argument Date constructor. Both take the same calendar components, but the constructor reads them in the running machine's local timezone while Date.UTC() reads them as UTC. It returns a raw timestamp, so wrap it in new Date(...) when you need an object.
When to reach for it
Use it any time the result must not depend on where the code runs: test fixtures, date-range boundaries stored server-side, scheduled jobs, and anything you are about to compare against a timestamp that came from a database. new Date(2024, 0, 1) produces seven different instants across seven timezones; Date.UTC(2024, 0, 1) produces one.
What trips people up
monthIndex is zero-based here exactly as it is in the constructor — Date.UTC(2024, 1, 29) is 29 February, not 29 January. Only the month is offset; the day is a normal 1-based day of the month.
Components normalize rather than clamp, so out-of-range values carry into the neighbouring field: a monthIndex of 15 rolls the year forward and lands on April. And a two-digit year is quietly shifted into the 1900s, so Date.UTC(95, 0, 1) is 1995.
Example
When to use it
- Create deterministic date fixtures that behave the same in CI and on a developer laptop
- Define the start and end of a reporting window that must match a UTC database column
- Convert year/month/day fields from a form into a single timestamp for storage
- Compute the number of days between two calendar dates without DST distorting the result
Frequently asked questions
When should I use Date.UTC() instead of new Date(y, m, d)?
Whenever the resulting instant must be identical regardless of the machine's timezone — tests, stored range boundaries, scheduled jobs. The constructor reads the same components as local time, so its result shifts with the runner's clock settings.
Does Date.UTC() return a Date object?
No, it returns a number of milliseconds since the epoch. Wrap it as new Date(Date.UTC(...)) when you need an object to call methods on.
Why is Date.UTC(2024, 12, 25) in 2025?
Month index 12 is one past December, so it rolls forward into January 2025. December is index 11 — subtract one from the human month number.
More examples
Why fixtures should use it
The UTC value always prints 2024-01-01T00:00:00.000Z. The local one only matches in UTC itself — elsewhere the difference equals getTimezoneOffset(), which is why local fixtures fail in CI.
const local = new Date(2024, 0, 1); // local midnight
const utc = new Date(Date.UTC(2024, 0, 1)); // UTC midnight
console.log(utc.toISOString());
console.log(local.getTime() === utc.getTime());
// The gap is exactly this machine's offset, in minutes
console.log((local.getTime() - utc.getTime()) / 60000);
console.log(local.getTimezoneOffset());Counting days between calendar dates
Because UTC has no daylight saving, every day is exactly 86,400,000 ms and the division is exact. The same arithmetic on local dates returns 30.958 across a spring-forward boundary.
const DAY = 86_400_000;
function daysBetween(a, b) {
return (Date.UTC(...b) - Date.UTC(...a)) / DAY;
}
console.log(daysBetween([2024, 0, 1], [2024, 1, 1])); // January
console.log(daysBetween([2024, 1, 1], [2024, 2, 1])); // leap February
console.log(daysBetween([2023, 1, 1], [2023, 2, 1])); // common February
console.log(daysBetween([2024, 0, 1], [2025, 0, 1])); // whole leap yearThe two-digit year rule
Years 0 to 99 map to 1900 + year, so 95 is 1995 and 0 is 1900. setUTCFullYear() has no such rule, which is the escape hatch for genuinely ancient dates.
console.log(Date.UTC(95, 0, 1) === Date.UTC(1995, 0, 1));
console.log(new Date(Date.UTC(95, 0, 1)).getUTCFullYear());
console.log(new Date(Date.UTC(0, 0, 1)).getUTCFullYear());
// To mean an actual early year, set it explicitly
const early = new Date(Date.UTC(2024, 0, 1));
early.setUTCFullYear(95);
console.log(early.getUTCFullYear());
Discussion