To remove time from date in TypeScript, copy the Date and call setHours(0, 0, 0, 0) on the copy. That sets the clock to local midnight and keeps a real Date you can compare. If you only need text, use toLocaleDateString("en-CA") for YYYY-MM-DD:
const day = new Date(date.getTime());
day.setHours(0, 0, 0, 0);
I ran every snippet on TypeScript 7.0.2 and Node.js v22.22.2 in strict mode, with the clock set to US Central time, because time zones change the answer.
Remove the time from a Date with setHours(0, 0, 0, 0)
Four zeros reset hours, minutes, seconds and milliseconds. Because setHours() changes the object it’s called on, I always copy first:
console.log("time zone:", Intl.DateTimeFormat().resolvedOptions().timeZone);
const fmt = (d: Date) => d.toLocaleString("en-US");
// Oct 20, 2026, 8:45:30 PM (months are 0-based)
const orderPlaced = new Date(2026, 9, 20, 20, 45, 30);
function removeTime(date: Date): Date {
const copy = new Date(date.getTime()); // work on a copy
copy.setHours(0, 0, 0, 0); // hours, minutes, seconds, ms
return copy;
}
const orderDay = removeTime(orderPlaced);
console.log("original: ", fmt(orderPlaced));
console.log("date only: ", fmt(orderDay));
// The trap: assigning a Date copies the reference, not the value
const shippedAt = new Date(2026, 9, 22, 14, 30);
const shipDay = shippedAt;
shipDay.setHours(0, 0, 0, 0);
console.log("shippedAt: ", fmt(shippedAt), "<- time is gone");
Output:
time zone: America/Chicago
original: 10/20/2026, 8:45:30 PM
date only: 10/20/2026, 12:00:00 AM
shippedAt: 10/22/2026, 12:00:00 AM <- time is gone

shipDay = shippedAt shares one object, so both lose it.That midnight value is what you need to check if a date is before today in TypeScript.
Why does setHours() give me a number instead of a Date?
It returns the new timestamp in milliseconds, not the Date. TypeScript catches it if you store that result as a date:
const signup = new Date(2026, 9, 20, 11, 15);
const signupDay: Date = signup.setHours(0, 0, 0, 0);
Output:
rmtime_returns.ts(3,7): error TS2322: Type 'number' is not assignable to type 'Date'.

setHours() returns a number.Call setHours() on its own line and keep using the Date variable.
Create a date-only Date with new Date(year, month, day)
You can also build a fresh Date from just the year, month and day. The original isn’t touched:
const placed = new Date(2026, 9, 20, 20, 45, 30); // 8:45 PM in Chicago
// Local midnight from the parts you keep
const localDay = new Date(placed.getFullYear(), placed.getMonth(), placed.getDate());
console.log("local midnight:", localDay.toString());
// UTC midnight of the same calendar date
const utcDay = new Date(Date.UTC(placed.getFullYear(), placed.getMonth(), placed.getDate()));
console.log("UTC midnight: ", utcDay.toISOString());
// Date-only strings parse as UTC
console.log("parsed string: ", new Date("2026-10-20").toString());
Output:
local midnight: Tue Oct 20 2026 00:00:00 GMT-0500 (Central Daylight Time)
UTC midnight: 2026-10-20T00:00:00.000Z
parsed string: Mon Oct 19 2026 19:00:00 GMT-0500 (Central Daylight Time)
Use local midnight for screens and “today” checks. UTC midnight is stable for storage but shows as the previous evening in the US, so format the date with a time zone in TypeScript on display.
Watch the last line: new Date("2026-10-20") is UTC midnight, so 7:00 PM on October 19 in Chicago. See converting a string to a date in TypeScript.
Get a YYYY-MM-DD string without the time (and avoid the toISOString trap)
The popular toISOString().split("T")[0] trick returns the UTC date. During daylight saving time, anything after 7:00 PM Central or 5:00 PM Pacific is already tomorrow in UTC:
const placed = new Date(2026, 9, 20, 20, 45, 30); // Oct 20, 8:45 PM Chicago
console.log("toISOString():", placed.toISOString());
console.log("split('T')[0]:", placed.toISOString().split("T")[0], "<- wrong day");
console.log("en-CA: ", placed.toLocaleDateString("en-CA"));
function toYmd(d: Date): string {
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return `${d.getFullYear()}-${month}-${day}`;
}
console.log("toYmd(): ", toYmd(placed));
console.log("en-US long: ", placed.toLocaleDateString("en-US", { dateStyle: "long" }));
const ymdIn = (tz: string) =>
new Intl.DateTimeFormat("en-CA", { timeZone: tz }).format(placed);
console.log("UTC: ", ymdIn("UTC"));
Output:
toISOString(): 2026-10-21T01:45:30.000Z
split('T')[0]: 2026-10-21 <- wrong day
en-CA: 2026-10-20
toYmd(): 2026-10-20
en-US long: October 20, 2026
UTC: 2026-10-21

en-CA and toYmd() keep the local date.The en-CA locale prints YYYY-MM-DD; toYmd() does it by hand with leading zeros via padStart in TypeScript. Add a timeZone when the date must match a specific city. For display, toDateString() works too.
Compare dates without the time in TypeScript
With both sides at midnight, use > and <, and getTime() for equality. === only checks whether two variables are the same object:
function removeTime(date: Date): Date {
const copy = new Date(date.getTime());
copy.setHours(0, 0, 0, 0);
return copy;
}
const dueDate = new Date(2026, 9, 20, 9, 0); // invoice due Oct 20, 9:00 AM
const paidAt = new Date(2026, 9, 20, 16, 30); // paid Oct 20, 4:30 PM
console.log("late, with time: ", paidAt > dueDate);
console.log("late, date only: ", removeTime(paidAt) > removeTime(dueDate));
console.log("same day via ===: ", removeTime(paidAt) === removeTime(dueDate));
console.log("same day getTime: ", removeTime(paidAt).getTime() === removeTime(dueDate).getTime());
// Across the Nov 1, 2026 DST change
const oct31 = new Date(2026, 9, 31);
const nov2 = new Date(2026, 10, 2);
const days = (nov2.getTime() - oct31.getTime()) / 86_400_000;
console.log("raw days:", days, "| rounded:", Math.round(days));
Output:
late, with time: true
late, date only: false
same day via ===: false
same day getTime: true
raw days: 2.0416666666666665 | rounded: 2

=== is false for equal dates, and a DST week needs Math.round.The 2.04 comes from the 25-hour day when DST ends on November 1, 2026; more in calculating the date difference in days in TypeScript.
Which method should you use to remove the time?
| You need | Use | Watch out for |
|---|---|---|
A Date at local midnight | Copy, then setHours(0, 0, 0, 0) | It mutates and returns a number |
A new date-only Date | new Date(y, m, d) | Months start at 0 |
| A stable stored value | Date.UTC(y, m, d) | Shows as the previous evening in the US |
A YYYY-MM-DD string | toLocaleDateString("en-CA") | Not toISOString() for local dates |
| Same-day checks | getTime() on midnight values | === compares references |
Building a calendar feature next? These should help:
- Get the first and last day of the week in TypeScript
- Get the week number from a date in TypeScript
- Format dates in TypeScript
Frequently asked questions
How do I remove the time from a date in TypeScript?
Copy the date with new Date(date.getTime()), then call setHours(0, 0, 0, 0) on the copy. You get a Date at local midnight.
Why does toISOString().split(“T”)[0] give tomorrow’s date?
It’s always UTC, and US evenings are already the next day in UTC. Use toLocaleDateString("en-CA") instead.
How do I get a date in YYYY-MM-DD format without the time?
Call date.toLocaleDateString("en-CA"), or join the local parts with padStart(2, "0").
How do I check if two dates are the same day?
Remove the time from both, then compare a.getTime() === b.getTime(). Plain === on two objects is always false.
Where is Date.prototype.setHours documented?
See Date.prototype.setHours() on MDN.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn