Date.prototype.setHours()
Sets the hours, and optionally minutes, seconds and milliseconds, of a date in local time.
setHours(hoursValue)
setHours(hoursValue, minutesValue)
setHours(hoursValue, minutesValue, secondsValue)
setHours(hoursValue, minutesValue, secondsValue, msValue)- Added in JavaScript ES1
Parameters
| Parameter | Type | Description |
|---|---|---|
$hoursValue | number | An integer between 0 and 23 representing the hour. Values outside the range shift the day accordingly. |
$minutesValueoptional | number= this.getMinutes() | An integer between 0 and 59 representing the minutes. Defaults to the value returned by getMinutes(). |
$secondsValueoptional | number= this.getSeconds() | An integer between 0 and 59 representing the seconds. If specified, minutesValue must be specified too. Defaults to the value returned by getSeconds(). |
$msValueoptional | number= this.getMilliseconds() | An integer between 0 and 999 representing the milliseconds. If specified, minutesValue and secondsValue must be specified too. Defaults to the value returned by getMilliseconds(). |
Return value
numberThe new timestamp of the modified Date object in milliseconds since the epoch. Returns NaN if any parameter is NaN or coerces to NaN, in which case the Date is set to Invalid Date.
Changelog
- PHP Modern enginesWhen the resulting local time does not exist or occurs twice because of a DST transition, engines follow Temporal's "compatible" disambiguation: the earlier instant for ambiguous times, and gaps are crossed forward.
setHours() writes the time-of-day onto an existing date in place. Its optional arguments are what make it worth reaching for: one call can set every time component at once.
The start-of-day idiom
d.setHours(0, 0, 0, 0) is the standard way to truncate a date to local midnight. Reach for it whenever you need to compare two instants by calendar day, group records into days, or compute a whole number of days between dates. Without the truncation, a diff between 23:59 on one day and 00:01 on the next divides out to almost zero days rather than one.
Passing only some arguments leaves the rest untouched, so setHours(9) on a 13:45:12 date gives 09:45:12 — the minutes and seconds survive. That is a common surprise when you expected 09:00:00.
What trips people up
Out-of-range values cascade rather than throw: setHours(25) moves into the next day, and setHours(9, 0, 100) becomes 09:01:40.
On a DST spring-forward day, local midnight may not exist in some zones — the result is shifted forward past the gap. And this is local time throughout; use setUTCHours() when the result must be identical everywhere.
Example
When to use it
- Truncate a timestamp to local midnight before comparing calendar days
- Pin a scheduled reminder to 09:00 on whatever day it lands
- Compute whole calendar days between two datetimes
- Build an end-of-day boundary at 23:59:59.999 for a query range
Frequently asked questions
How do I set a date to midnight in JavaScript?
Call d.setHours(0, 0, 0, 0), which zeroes the hours, minutes, seconds and milliseconds in local time. All four arguments are needed — setHours(0) alone leaves the existing minutes and seconds in place.
Why does setHours() change the day?
Because out-of-range values cascade instead of throwing: setHours(24) or higher rolls into the following day, and negative values roll back into the previous one. This is deliberate and makes hour arithmetic work without bounds checks.
Does setHours(0,0,0,0) always give exactly midnight?
Not in every time zone on every day — where a daylight saving transition skips local midnight, the result is pushed forward past the gap to the first instant that exists. Use setUTCHours(0,0,0,0) if you need a guaranteed 00:00 boundary.
More examples
Whole calendar days between two datetimes
The raw subtraction says the two instants are two minutes apart, which is true but useless for a calendar. Truncating both copies to midnight first turns the same pair into the one day the user expects.
function daysBetween(a, b) {
const x = new Date(a); x.setHours(0, 0, 0, 0);
const y = new Date(b); y.setHours(0, 0, 0, 0);
return Math.round((y - x) / 86400000);
}
const late = new Date(2024, 0, 1, 23, 59);
const early = new Date(2024, 0, 2, 0, 1);
console.log((early - late) / 86400000); // ~0.0014 — raw diff
console.log(daysBetween(late, early)); // 1 — calendar daysHours overflow into the next day
Every out-of-range value cascades upward instead of throwing: hour 25 becomes 01:00 the next day, 100 seconds becomes one minute and 40 seconds, and hour -1 walks back into the previous year.
const d = new Date(2024, 0, 31, 10, 0, 0);
d.setHours(25);
console.log(d.toDateString(), d.getHours()); // Thu Feb 01 2024 1
const e = new Date(2024, 0, 1, 9, 0, 0);
e.setHours(9, 0, 100); // 100 seconds
console.log(e.getHours(), e.getMinutes(), e.getSeconds()); // 9 1 40
const f = new Date(2024, 0, 1, 12, 0);
f.setHours(-1);
console.log(f.toDateString(), f.getHours()); // Sun Dec 31 2023 23
Discussion