Introduction
\nWorking with dates and time is one of the most common, yet most treacherous tasks in web development. The standard Date object in JavaScript, despite its versatility, has a number of limitations: lack of built-in time zone support (except UTC and local time), inconvenient formatting methods, and difficulties in calculating the difference between dates. In this article, we will cover advanced techniques for working with dates in the Node.js environment that will help you write reliable and understandable code.
1. Intl.DateTimeFormat: Powerful Formatting Without Third-Party Libraries
\nModern JavaScript provides the built-in Intl.DateTimeFormat API, which allows flexible formatting of dates and time with locale support. This is an ideal tool if you don't need the full power of third-party libraries.
Basic Usage
\nCreate a formatter instance by passing a locale and an options object:
\nconst date = new Date('2024-12-25T10:30:00Z');\n\n// Formatting for Russian locale\nconst ruFormatter = new Intl.DateTimeFormat('ru-RU', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'long',\n hour: '2-digit',\n minute: '2-digit',\n timeZone: 'Europe/Moscow'\n});\n\nconsole.log(ruFormatter.format(date));\n// Output: "среда, 25 декабря 2024 г. в 13:30"\n\nWorking with Time Zones
\nThe key advantage of Intl.DateTimeFormat is time zone support via the timeZone option. You can display the same date in different time zones:
const date = new Date();\n\nconst formatters = {\n 'New York': new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }),\n 'Tokyo': new Intl.DateTimeFormat('ja-JP', { timeZone: 'Asia/Tokyo', dateStyle: 'full', timeStyle: 'long' }),\n 'London': new Intl.DateTimeFormat('en-GB', { timeZone: 'Europe/London', dateStyle: 'full', timeStyle: 'long' })\n};\n\nfor (const [city, fmt] of Object.entries(formatters)) {\n console.log(`${city}: ${fmt.format(date)}`);\n}\n\nFormatting Date Ranges
\nThe API can also format ranges using the formatRange method:
const start = new Date('2024-01-01');\nconst end = new Date('2024-01-05');\n\nconst rangeFormatter = new Intl.DateTimeFormat('ru-RU', {\n month: 'long',\n day: 'numeric'\n});\n\nconsole.log(rangeFormatter.formatRange(start, end));\n// Output: "1–5 января"\n\n2. Date Manipulations: Addition, Subtraction, and Difference
\nThe standard Date is poorly suited for arithmetic. Let's look at two approaches: pure JavaScript and popular libraries.
Pure JavaScript: Working with Milliseconds
\nThe simplest way is to convert the date to a Unix timestamp (milliseconds since January 1, 1970) and perform operations:
\nfunction addDays(date, days) {\n const result = new Date(date);\n result.setTime(result.getTime() + days * 24 * 60 * 60 * 1000);\n return result;\n}\n\nfunction diffDays(date1, date2) {\n const msDiff = Math.abs(date2.getTime() - date1.getTime());\n return Math.floor(msDiff / (1000 * 60 * 60 * 24));\n}\n\nconst today = new Date('2024-10-01');\nconst future = addDays(today, 30);\nconsole.log(future); // 2024-10-31\nconsole.log(diffDays(today, future)); // 30\nDisadvantage: does not account for daylight saving time, leap seconds, and varying month lengths.
\n\ndate-fns Library: A Functional and Lightweight Approach
\ndate-fns is a modular library where each function is a separate module. This prevents bloating the bundle:
// Installation: npm install date-fns\nconst { addDays, subMonths, differenceInDays, format } = require('date-fns');\nconst { ru } = require('date-fns/locale');\n\nconst startDate = new Date(2024, 0, 15); // January 15, 2024\n\nconst plusWeek = addDays(startDa