Best Practices

Building reliable applications that handle dates and times correctly is not easy!

It works on your machine, but you run into issues when you deploy it to machines in different timezones and with users all around the world. These guidelines will help you avoid common pitfalls and build maintainable calendar applications.

Core Principles

1. Always Specify Timezones Explicitly

I can not stress this enough. Always set timezone explicitly! Never rely on the system timezone for any date operations as it creates unpredictable behavior between environments. The Date() object is not your friend as it's not timezone aware.

Read more about this in Why NOT to use Date.

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());

User experience tip: If the user have not selected Country or Timezone in our app, default to the browsers local timezone, but never rely on it. This is how most calendar applications like Outlook handle timezone selection.

2. Store as Timestamps, Display with Calendar Dates

Timestamps are the perfect storage for date and time as they are timezone agnostic performant and serializable. Use timezone aware calendar library like Datezone when you want to display and do calendar math.

Read more about why you should use timestamps in Why use Timestamps.

guides/best-practices/user-settings-probably-set-in-a-database-or-local-storage.ts
import { addDays, calendarToTimestamp, format } from "datezone";

// 💡 User settings, store in a database, local storage or similar
// Do not rely on browsers timezone.
const userLocale = "en-US";
const userTimezone = "America/New_York";

// ✅ Store Dates as timestamp in your state, (url, local storage or database)
const calendarEvent = {
	endTime: Date.now(),
	id: "123",
	name: "Team Meeting",
	// Calendar date: 2025-03-08 5PM EST
	startTime: calendarToTimestamp(2025, 3, 8, 17, 0, 0, 0, userTimezone),
};

// ✅ Whenever you you want to display a date or do calendar operations,
// set timezone explicitly, (For example the user's preferred timezone)
calendarEvent.startTime = addDays(calendarEvent.startTime, 1, userTimezone);

const formattedDate = format(calendarEvent.startTime, "MMM dd, yyyy HH:mm", {
	locale: userLocale,
	timeZone: userTimezone,
});

console.log(formattedDate);

3. Never Use simple arithmetic for Calendar Operations

Don't use simple math on timestamps for date operations. Daylight Savings Time (DST) transitions make this unreliable.

guides/how-dst-works/at-200-am-est-clocks-spring-forward-to-300-am-edt.ts
// Demonstrates how naive duration calculations ignore the "skipped" hour when Daylight Saving Time starts in New York (America/New_York).

// 1:59 AM EST (UTC-5) — just before the clocks spring forward
const before = new Date("2024-03-10T01:59:00-05:00");

// 3:00 AM EDT (UTC-4) — the next valid local time after the DST jump
const after = new Date("2024-03-10T03:00:00-04:00");

// How many minutes does JavaScript think have passed?
const diffMinutes = (after.getTime() - before.getTime()) / 60_000;
console.log("diffMinutes", diffMinutes); // 👉 1 minute (!)

Read more about DST and common pitfalls in how DST works

DST gotcha: During DST transitions, some days are 23 or 25 hours long. Simple arithmetic might give you the wrong calendar date twice a year.

Database, Storage and API Design

Database Storage Details: Postgres & MySQL

PostgreSQL:

  • Store timestamps as either TIMESTAMP or as a BIGINT (milliseconds since epoch, UTC).
  • Do not use TIMESTAMP WITH TIME ZONE (TIMESTAMPTZ) for storage. Always store dates in UTC, regardless of user location. This makes it easy to compare dates and run statistical queries across users.

Note: Using TIMESTAMP (without time zone) for storage is a strongly opinionated choice. I believe Timezone handling should always be managed in your business logic layer, not in the database. This keeps your data unambiguous and avoids subtle bugs caused by implicit timezone conversions in SQL engines. Let your application code handle all timezone conversions and calendar math.

  • The popular pg npm package will return an ISO string for TIMESTAMP columns and a number for BIGINT columns. Use datezone's fromIsoString() or Date.parse().getTime() to convert ISO strings to timestamps.
-- ✅ PostgreSQL example
CREATE TABLE events (
  id UUID PRIMARY KEY,
  name TEXT NOT NULL,
  created_at TIMESTAMP NOT NULL,  
  -- ✅ You can also use BIGINT for performance
  start_time BIGINT,  
  end_time BIGINT
);

MySQL:

  • Use the TIMESTAMP column type and set the connection option { dateStrings: true } in your MySQL driver. This ensures you get string values instead of JavaScript Date objects, which avoids subtle bugs and extra allocations.
  • As with Postgres, always store and interpret values as UTC.
-- ✅ MySQL example
CREATE TABLE events (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name TEXT NOT NULL,
  created_at TIMESTAMP NOT NULL,  
  -- ✅ You can also use BIGINT for performance
  start_time BIGINT,  
  end_time BIGINT
);
guides/best-practices/example-1.ts
import { createConnection } from "mysql2";

const _connection = createConnection({
	database: "test",
	dateStrings: true, // Set to true to return ISO Strings instead of Date objects,
	host: "localhost",
	user: "root",
});
  • Storing all dates in UTC (as numbers or ISO strings) ensures consistent, unambiguous comparisons and makes analytics/statistical queries much simpler.
  • Timezone conversion and related bugs should be in your business layer in code. Not in the Database.

In API's, use Timestamps or ISO Strings

When using an API, always use timestamps or ISO strings for dates.

{
  "id": 1,
  "name": "Event 1",
  "created_at": "2021-01-01T00:00:00.000Z",
  "start_time": 1614556800000,
  "end_time": 1614556800000
}

Date object is not supported in JSON. Don't use it in API's.

Read more about this in Why NOT to use Date.

Summary

Following these best practices will help you build robust, maintainable applications with reliable date and time handling:

  1. Always specify timezones explicitly
  2. Store timestamps, display with timezone context
  3. Never use arithmetic for calendar operations
  4. Store as TIMESTAMP or BIGINT in Database
  5. In API's use Timestamps or ISO Strings

These practices, combined with datezone's timezone-aware calendar functions, will eliminate the vast majority of date-related bugs in your applications.

On this page