Why NOT to use Date

JavaScript's Date object is one of the most problematic APIs in the language. While it seems convenient at first, it's the source of countless bugs and unpredictable behavior in applications. Here's why you should avoid it at any cost.

The Core Problems

1. No Timezone Support

The Date object doesn't support explicit timezones. It only knows about the local system timezone and UTC, making it really difficult to work with dates in a predictable way.

guides/why-not-to-use-date/example-1.ts
const date = new Date("2024-01-01");
// Could be anything 0, 1, 23, etc. depending on browser or server timezone
console.log(date.getHours());

Machine-dependent behavior: The same code produces different results depending on where it's executed. This makes your application unpredictable and hard to test.

  • The JavaScript Date object reflects the host system's local timezone.

  • There is no API in JavaScript to override this.

2. Confusing constructor

The Date object's constructor string parser have strange behavours. These might lead to errors that are really hard to track down.

guides/why-not-to-use-date/example-2.ts
// Same same but different:

// Use a Date in the constructor, interpeted as UTC, no problem.
console.log(new Date("2024-01-01"));

// Add Time to the string, now it's interpreted as LOCAL time.
console.log(new Date("2024-01-01T00:00:00"));

// Add a Z to the end of the string, now it's interpreted as UTC again
console.log(new Date("2024-01-01T00:00:00Z"));

3. Confusing API Method Names

The Date object has poorly named methods that don't match what you'd expect, making code hard to read and prone to errors.

guides/why-not-to-use-date/confusing-api.ts
// JavaScript Date has confusing method names and behaviors

const date = new Date("2024-01-15"); // Monday, January 15th, 2024

// Confusing: getDay() returns day of WEEK, not day of month
console.log(date.getDay()); // 1 (Monday)
// Expected: Should be called getDayOfWeek() or getWeekday()

// Confusing: 0 = Sunday, not Monday (differs from ISO 8601)
const sunday = new Date("2024-01-14");
console.log(sunday.getDay()); // 0 (Sunday)
// ISO 8601 standard: Monday = 1, Sunday = 7

// Confusing: getDate() returns day of MONTH, not the full date
console.log(date.getDate()); // 15 (day of month)
// Expected: Should be called getDayOfMonth()

// What you'd expect vs what you get:
// date.getDay() → should be day of month (15) → actually day of week (1)
// date.getDate() → should be full date → actually day of month (15)

// The correct but counter-intuitive way:
const dayOfWeek = date.getDay(); // 0-6, Sunday = 0
const dayOfMonth = date.getDate(); // 1-31
const fullDate = date.toString(); // Full date string

console.log(`Day of week: ${dayOfWeek}`); // 1
console.log(`Day of month: ${dayOfMonth}`); // 15
console.log(`Full date: ${fullDate}`); // Mon Jan 15 2024...

You would expect getDate() to also use a 0-based index for the day of the month just like getDay(), but it doesn't.

Counter-intuitive naming:

  • getDay() returns day of week (0-6), not day of month
  • getDate() returns day of month (1-31), not the full date
  • Day of week uses 0=Sunday instead of ISO 8601 standard where Monday=1

4. Mutable State = Bugs

Date objects are mutable, which might lead to unexpected side effects and hard-to-track bugs.

guides/why-not-to-use-date/example-3.ts
const date = new Date("2024-01-01"); // Creates a new Date 2024-01-01 00:00 UTC

console.log("Unmodified date", date);
const newDate = new Date(date.setDate(date.getDate() + 1));
console.log("New date", newDate);
console.log("Modified date", date);

Mutation bugs: Methods like setHours(), setDate(), etc. modify the original object instead of returning a new one.

  • Violates the principle of immutability and can cause subtle bugs.
  • Confusing return values: setDate() returns a timestamp, making it appear like an immutable function when it also mutates the original object.

5. Unpredictable Results

The same code returns different results depending on the system timezone, making unit testing unreliable.

guides/why-not-to-use-date/example-4.ts
// This represents midnight UTC on Jan 1, 2024
const date = new Date("2024-01-01");
const hours = date.getHours();

// Imagine this is unit tests, and you are testing a function that returns a date.
console.log(hours === 0); // ✅ Works in UTC
console.log(hours === 19); // ✅ Works in EST (UTC-5)
console.log(hours === 16); // ✅ Works in PST (UTC-8)
console.log(hours === 9); // ✅ Works in JST (UTC+9)

5. Not Serializable

Date objects don't serialize well. When you send them over HTTP or store them in JSON, you lose the Date() object.

guides/why-not-to-use-date/example-5.ts
const date = new Date();
const json = JSON.stringify(date);
const parsed = JSON.parse(json);

// parsed.date is now a string, not a Date object
console.log(typeof date); // "object"
console.log(typeof parsed); // "string"

Serialization problems: Libraries like superjson exist to work around this, but they add complexity and overhead to your application.

6. Only Supports Gregorian Calendar

The Date object only works with the Gregorian calendar. While this calendar is widely used, many cultures use different calendar systems (like Islamic, Hebrew, Thai Buddhist, or Chinese calendars).

Limited calendar support: JavaScript Date() only supports the Gregorian calendar.

The Alternative: Timestamps

JavaScript has a much better built-in native type for handling dates: number (timestamps)!

Why Timestamps Are Better

  • Immutable: It's just numbers
  • Serializable: Work perfectly with JSON
  • Predictable: Always represent the same moment in time no matter environment, timezone or calendar system
  • Efficient: No extra object allocation or garbage collection overhead
  • Testable: Easy to create predictable tests that works everywhere.
guides/why-not-to-use-date/example-6.ts
// Clean, predictable, testable
const timestamp = Date.now();
const oneHourLater = timestamp + 60 * 60 * 1000;

// This works the same everywhere
console.log(oneHourLater - timestamp === 3600000);

Summary

The JavaScript Date object is tricky and are a big cause of Date & Time related bugs in global applications.

Next, learn about why timestamps are the better choice for your applications.

On this page