引言
\n日期和时间处理是 Web 开发中最常见但也最棘手的任务之一。JavaScript 中的标准 Date 对象虽然通用,但存在一些限制:缺乏对时区的内置支持(除了 UTC 和本地时间)、格式化方法不便以及计算日期差异复杂。在本文中,我们将探讨在 Node.js 环境中处理日期的高级技巧,帮助您编写可靠且清晰的代码。
1. Intl.DateTimeFormat:无需第三方库的强大格式化功能
\n现代 JavaScript 提供了内置的 Intl.DateTimeFormat API,它允许您根据区域设置灵活地格式化日期和时间。如果您不需要第三方库的全部功能,这是一个理想的工具。
基本用法
\n创建一个格式化器实例,传入区域设置和包含选项的对象:
\nconst date = new Date('2024-12-25T10:30:00Z');\n\n// 为俄语区域设置进行格式化\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// 输出:"среда, 25 декабря 2024 г. в 13:30"\n\n处理时区
\nIntl.DateTimeFormat 的关键优势在于通过 timeZone 选项支持时区。您可以在不同时区显示同一日期:
const date = new Date();\n\nconst formatters = {\n '纽约': new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }),\n '东京': new Intl.DateTimeFormat('ja-JP', { timeZone: 'Asia/Tokyo', dateStyle: 'full', timeStyle: 'long' }),\n '伦敦': 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\n格式化日期范围
\n该 API 还可以使用 formatRange 方法格式化日期范围:
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// 输出:"1–5 января"\n\n2. 日期操作:加法、减法和差异计算
\n标准的 Date 对象不太适合算术运算。我们来看两种方法:纯 JavaScript 和流行的库。
纯 JavaScript:使用毫秒数
\n最简单的方法是将日期转换为 Unix 时间戳(自 1970 年 1 月 1 日以来的毫秒数)并执行操作:
\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\n缺点:未考虑夏令时、闰秒和不同月份的长度。
\n\ndate-fns 库:函数式且轻量级的方法
\ndate-fns 是一个模块化库,每个函数都是一个独立的模块。这有助于避免包体积膨胀:
// 安装: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); // 2024 年 1 月 15 日\n\nconst plusWeek = addDays(startDa