getHours()
ES1+Returns the hour of the given date according to local time, as an integer from 0 to 23. The value follows the 24-hour clock, so midnight is 0 and 11 PM is 23. It reflects the runtime's local time zone, including any daylight saving offset in effect at that instant.
Syntax
date.getHours()Return Value
A number (0-23) representing the hour
Examples
const date = new Date('2024-01-15T14:30:00');
console.log(date.getHours()); 📌 When to Use
Use getHours() when behavior should depend on the local clock hour: time-of-day greetings, switching a UI into night mode, gating features to business hours, bucketing analytics events into hourly histograms, or picking quiet hours for notifications. It answers "what does the wall clock say where this code runs", which is exactly right for client-side personalization, and exactly wrong for anything that must be consistent across regions, where getUTCHours() or an explicit time zone via Intl.DateTimeFormat with a timeZone option is the correct tool. Business-hours checks deserve care: "9 to 5 in the store's time zone" is a property of the store, not of the visitor's laptop, so compute it by formatting the instant into the store's IANA zone rather than trusting the browser's locale clock. Also remember that daylight saving makes local hours non-uniform: one hour a year does not exist (clocks jump from 01:59 to 03:00) and another occurs twice, so hour-based schedulers should be built on timestamps or cron-style infrastructure rather than naive "when getHours() === 2" checks, which can fire twice or never on transition days.
⚠️ Common Mistakes
Expecting 12-hour values or an AM/PM flag. getHours() is strictly 0-23; 1 PM is 13. Rendering it directly gives users "14:30" where "2:30 PM" was wanted; the conversion is hours % 12 || 12, and the || 12 detail (so 0 and 12 both display as 12) is what hand-rolled versions usually miss.
Comparing hours across time zones: an event at 14:00 in the user's browser is not 14:00 for your server or other users. Storing bare hour numbers without a time zone reference makes "send at 9 AM" features fire at the wrong local time for everyone but the developer.
Scheduling exact-hour work by polling getHours(). On DST spring-forward days the 2 AM hour may never exist, so a "run when hour is 2" job silently skips; on fall-back days the repeated hour runs it twice. Schedule against UTC timestamps or use platform schedulers.
Building hour ranges with inverted or inclusive-end logic: if (h >= 22 && h <= 6) is never true because no hour satisfies both; overnight ranges must be expressed as h >= 22 || h < 6. Off-by-one at range ends (< 17 versus <= 17) also shifts closing time by an hour.
Parsing a date-time string without an offset and assuming UTC: new Date("2024-01-15T14:30") is 14:30 local, while "2024-01-15T14:30Z" is 14:30 UTC. The two differ by the whole timezone offset, so getHours() on the wrong variant is off by many hours, not subtly.
✅ Best Practices
Keep raw getHours() logic for genuinely local concerns (greetings, theming) and route everything shared, schedules, logs, cross-user comparisons, through UTC or an explicit IANA time zone with Intl.DateTimeFormat({ timeZone }).
Format times for display with toLocaleTimeString or Intl.DateTimeFormat instead of manual AM/PM math; hourCycle and hour12 options produce the locale-correct clock (including locales that write 0-23 by default) without conditional code.
Express overnight windows with OR logic and half-open intervals: start <= h || h < end for wrap-around ranges, h >= start && h < end otherwise. Half-open intervals compose without gaps or double-counting at boundaries.
For recurring local-time events (a 9 AM daily reminder), store the intended local time plus the IANA zone (for example "09:00" and "Asia/Seoul") and materialize concrete timestamps per occurrence; storing a single UTC hour breaks whenever DST shifts the offset.
The Temporal API separates these concepts cleanly: Temporal.PlainTime for clock times without a zone, Temporal.ZonedDateTime for instants in a zone, with explicit disambiguation options for the DST-skipped and repeated hours that Date handles by silent adjustment.
⚡ Performance Notes
getHours() is a constant-time field read once the engine has expanded the timestamp into local components, which it caches per Date instance; calling it is as cheap as any getter in the language. Costs appear at a different layer: each new Date() allocation in a per-event handler creates garbage, so hourly bucketing of large event arrays should hoist one Date or derive the hour arithmetically from the epoch value when the zone is fixed (for UTC, Math.floor(ms / 3600000) % 24 avoids Date entirely). Note also that the local-time conversion consults the environment's time zone data; that lookup is fast and cached, but formatting-based alternatives like toLocaleTimeString construct Intl machinery that is hundreds of times slower per call, so never use formatting just to extract a numeric hour.
🌍 Real World Example
Dynamic Greeting Message
Time-aware greetings are a small personalization touch used by dashboards, email clients, and assistants alike. This example maps getHours() ranges onto morning, afternoon, evening, and night salutations, keeping the range boundaries in one place so product decisions ("does evening start at 17 or 18?") are one-line changes. Because it runs on the visitor's device, the local-time semantics of getHours() are exactly right here, no time zone bookkeeping needed. The same range-mapping pattern drives automatic dark-mode switching and "quiet hours" notification muting.
function getGreeting(userName) {
const hour = new Date().getHours();
let greeting, emoji;
if (hour >= 5 && hour < 12) {
greeting = 'Good morning';
emoji = '☀️';
} else if (hour >= 12 && hour < 17) {
greeting = 'Good afternoon';
emoji = '🌤️';
} else if (hour >= 17 && hour < 21) {
greeting = 'Good evening';
emoji = '🌆';
} else {
greeting = 'Good night';
emoji = '🌙';
}
return {
message: `${greeting}, ${userName}! ${emoji}`,
timeOfDay: greeting.split(' ')[1],
currentHour: hour
};
}
console.log(getGreeting('Alex'));
// { message: 'Good afternoon, Alex! 🌤️', timeOfDay: 'afternoon', currentHour: 14 }