JavaScript Date: Working with Dates and Times in JS

JavaScript's Date object is the built-in way to work with dates, times, timestamps, and time zones. It is used for everything from showing a post's published time to scheduling reminders and measuring elapsed time.

Quick answer: Date is the built-in JavaScript object for representing a specific moment in time. You create one with new Date(), then read or change values with methods like getFullYear(), toISOString(), and getTime().

Difficulty: Beginner

You'll understand this better if you know: basic JavaScript variables, functions, and how objects store data and behavior.

1. What Is Date?

Date is JavaScript's standard object for representing points in time. Internally, a date value is stored as a number of milliseconds since the Unix epoch: midnight at the start of January 1, 1970, UTC.

  • It can represent a specific instant, not just a calendar day.
  • It stores time with millisecond precision.
  • It can display values in local time or UTC.
  • It includes parsing, formatting, and arithmetic methods.

That means a Date object is useful for both human-friendly calendar display and machine-friendly time calculations.

2. Why Date Matters

Nearly every application needs dates and times at some point. A shopping app may need delivery dates, a dashboard may show last-updated times, and a scheduling tool may compare two timestamps.

JavaScript's Date matters because it is available everywhere JavaScript runs, including browsers and Node.js. You do not need a library for basic date storage, comparison, or formatting.

At the same time, Date is also one of the most misunderstood built-in objects because time zones, parsing rules, and locale formatting can produce unexpected results. Learning the built-in behavior helps you avoid subtle bugs.

3. Basic Syntax

The most common way to create a date is with new Date(). You can create the current moment, a specific timestamp, or a date from a string.

Create the current date and time

This creates a Date for the exact moment the code runs.

JavaScript
const now = new Date();

Create a date from year, month, and day

The month number is zero-based, so 0 means January and 11 means December.

JavaScript
const independenceDay = new Date(2026, 6, 4);

Create a date from a timestamp

A timestamp is the number of milliseconds since the Unix epoch.

JavaScript
const fromTimestamp = new Date(1719830400000);

Once you have a date, you can read parts of it with methods such as getFullYear(), getMonth(), getDate(), and getHours().

4. Step-by-Step Examples

Example 1: Get today's date and format it

This example creates a Date object for the current moment and prints a simple local date string.

JavaScript
const today = new Date();

console.log(today.toDateString());

This is useful for quick display, though it is not ideal for custom formatting.

Example 2: Read the individual parts of a date

Sometimes you need the year, month, and day separately.

JavaScript
const date = new Date(2025, 0, 15);

const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();

console.log(year, month, day);
Output✓ Tested · Node 24
2025 0 15

Remember that getMonth() returns a zero-based month, so January is 0.

Example 3: Compare two dates

You can compare timestamps directly by converting each date with getTime().

JavaScript
const start = new Date(2025, 0, 1);
const end = new Date(2025, 0, 31);

if (end.getTime() > start.getTime()) {
  console.log("End is after start");
}
Output✓ Tested · Node 24
End is after start

Because timestamps are just numbers, date comparisons are simple and reliable.

Example 4: Format a date for display

The toLocaleDateString() method uses the user's locale to format a readable date.

JavaScript
const eventDate = new Date(2025, 10, 5);

const formatted = eventDate.toLocaleDateString("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(formatted);
Output✓ Tested · Node 24
November 5, 2025

This produces a human-friendly string such as November 5, 2025.

5. Practical Use Cases

  • Showing a post's published date in a blog or CMS.
  • Calculating how many days remain until an event or deadline.
  • Recording when a user last signed in or updated a profile.
  • Checking whether an action happened before or after another event.
  • Converting API timestamps into readable local times.
  • Scheduling reminders, notifications, or background jobs.

In most projects, Date is used for both storage and display, but the best practice is usually to store timestamps or ISO strings and format them only when needed.

6. Common Mistakes

Mistake 1: Forgetting that months are zero-based

JavaScript's date constructor treats months as 0 through 11. New developers often pass 1 for January and get the wrong month.

Problem: This creates February 15, not January 15, because the month argument starts at zero.

JavaScript
const wrong = new Date(2025, 1, 15);
console.log(wrong.toDateString());
Output✓ Tested · Node 24
Sat Feb 15 2025

Fix: Use 0 for January, 1 for February, and so on.

JavaScript
const correct = new Date(2025, 0, 15);
console.log(correct.toDateString());
Output✓ Tested · Node 24
Wed Jan 15 2025

The corrected version works because it matches JavaScript's month indexing rules.

Mistake 2: Comparing dates with == or ===

Two different Date objects are different object references, even if they represent the same moment.

Problem: Reference comparison does not compare the actual time value, so these checks usually fail even when the dates look identical.

JavaScript
const a = new Date(2025, 0, 1);
const b = new Date(2025, 0, 1);

console.log(a === b);
Output✓ Tested · Node 24
false

Fix: Compare the timestamps with getTime() or valueOf().

JavaScript
const a = new Date(2025, 0, 1);
const b = new Date(2025, 0, 1);

console.log(a.getTime() === b.getTime());
Output✓ Tested · Node 24
true

The corrected version works because timestamps compare the actual moment in time.

Mistake 3: Assuming parsed date strings are always reliable

String parsing with Date can be inconsistent if the format is not ISO 8601 or otherwise well supported. Some strings may create an invalid date without an obvious error.

Problem: A date string can produce Invalid Date, and methods such as getTime() then return NaN.

JavaScript
const parsed = new Date("15/01/2025");

console.log(parsed.toString());
console.log(parsed.getTime());
Output✓ Tested · Node 24
Invalid Date
NaN

Fix: Use a reliable format such as ISO 8601, or build the date from numeric parts yourself.

JavaScript
const parsed = new Date("2025-01-15T00:00:00Z");

if (Number.isNaN(parsed.getTime())) {
  console.log("Invalid date");
}

The corrected version works because ISO-style input is far more predictable across JavaScript engines.

7. Best Practices

Practice 1: Store timestamps or ISO strings, not formatted text

Formatted strings are good for display, but they are a poor storage format because they depend on locale and are harder to compare.

JavaScript
const stored = "2025-01-15T14:30:00.000Z";
const date = new Date(stored);

This approach keeps your data consistent and easy to reconstruct later.

Practice 2: Use UTC when you need absolute time

If the time must mean the same thing everywhere, use UTC methods or ISO timestamps with Z at the end.

JavaScript
const utcDate = new Date("2025-01-15T12:00:00Z");

console.log(utcDate.toISOString());
Output✓ Tested · Node 24
2025-01-15T12:00:00.000Z

UTC avoids many time zone surprises when data is shared across systems.

Practice 3: Validate dates before using them

A date object can exist but still be invalid. Check it before formatting or calculating with it.

JavaScript
const candidate = new Date("not a date");

if (Number.isNaN(candidate.getTime())) {
  console.log("Please enter a valid date");
}
Output✓ Tested · Node 24
Please enter a valid date

This prevents downstream bugs from invalid input.

8. Limitations and Edge Cases

  • Date uses the system time zone by default, which can change how a moment is displayed.
  • Daylight saving time can make local times repeat or skip, so adding 24 hours does not always mean the same local clock time tomorrow.
  • Parsing non-ISO strings is implementation-dependent and can behave differently across environments.
  • Months are zero-based in the constructor and getters, which is a common source of off-by-one bugs.
  • Date has millisecond precision, so it is not suited for high-resolution timing.
  • Very large or out-of-range values can produce an invalid date rather than a clean error.

If you need calendar-only values, such as a birthday without a time of day, be careful: Date still represents a moment in time, so time zone conversion can shift the displayed day.

9. Practical Mini Project

This mini project builds a small function that prints a countdown message for an event. It combines creation, comparison, and formatting in one place.

JavaScript
function daysUntilEvent(eventDate) {
  const now = new Date();
  const target = new Date(eventDate);

  if (Number.isNaN(target.getTime())) {
    return "Invalid event date";
  }

  const msPerDay = 24 * 60 * 60 * 1000;
  const diff = target.getTime() - now.getTime();
  const days = Math.ceil(diff / msPerDay);

  if (days < 0) {
    return "The event has already passed";
  }

  return `${days} day(s) left`;
}

console.log(daysUntilEvent("2025-12-31T00:00:00Z"));

This example shows a practical workflow: validate the input, compare timestamps, and return a readable result.

10. Key Points

  • Date represents a specific moment in time, not just a calendar day.
  • The internal value is milliseconds since the Unix epoch.
  • Month numbers are zero-based in constructors and getters.
  • Use timestamps for comparisons and calculations.
  • Use locale-aware formatting for user-facing display.
  • Prefer ISO 8601 or numeric construction for reliable parsing.

11. Practice Exercise

  • Create a function named formatMeetingDate that takes a date string.
  • Return "Invalid date" if the input cannot be parsed.
  • Otherwise, return a string in the form "Wednesday, March 12, 2025".
  • Use built-in Date methods only.

Expected output: A readable, validated long-form date string.

Hint: Check the result with Number.isNaN(date.getTime()), then use toLocaleDateString() with options.

Show solution
JavaScript
function formatMeetingDate(dateString) {
  const date = new Date(dateString);

  if (Number.isNaN(date.getTime())) {
    return "Invalid date";
  }

  return date.toLocaleDateString("en-US", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric"
  });
}

console.log(formatMeetingDate("2025-03-12T09:00:00Z"));
console.log(formatMeetingDate("hello"));
Output✓ Tested · Node 24
Wednesday, March 12, 2025
Invalid date

12. Final Summary

Date is the standard JavaScript object for working with moments in time, timestamps, and readable date output. It is simple to create, but its behavior around months, parsing, and time zones requires attention.

For most everyday work, the safest approach is to store dates as ISO strings or timestamps, compare values with getTime(), and format output only when you display it to a user. That keeps your code predictable and reduces time zone surprises.

If you want to go further, the next topic to learn is JavaScript time zones and locale formatting, because those are the pieces that most often determine whether a date feature feels correct to users.