表达日期与时间 - 知蛛网Date 对象基础
1. 创建 Date 对象
// 1. 当前日期时间
const now = new Date();
console.log(now); // 当前日期时间的Date对象
// 2. 指定时间戳(自1970-01-01 00:00:00 UTC以来的毫秒数)
const timestamp = new Date(1640995200000); // 2022-01-01 00:00:00 UTC
console.log(timestamp);
// 3. 日期时间字符串(推荐使用ISO格式)
const dateStr = new Date("2024-01-15T10:30:00");
const dateStr2 = new Date("January 15, 2024 10:30:00");
const dateStr3 = new Date("2024/01/15 10:30:00");
console.log(dateStr);
// 4. 年月日时分秒毫秒(月份从0开始)
const specific = new Date(2024, 0, 15, 10, 30, 0, 0); // 2024年1月15日 10:30:00.000
console.log(specific);
// 5. 只传年月日(时分秒默认为0)
const dateOnly = new Date(2024, 0, 15);
console.log(dateOnly); // 2024-01-15 00:00:00
// 6. Date.now() - 获取当前时间戳
const currentTimestamp = Date.now();
console.log(currentTimestamp); // 164xxxxxxxxxx 毫秒数
// 7. Date.parse() - 解析日期字符串为时间戳
const parsed = Date.parse("2024-01-15T10:30:00");
console.log(parsed); // 1705300200000
// 8. Date.UTC() - 返回UTC时间的时间戳
const utcTimestamp = Date.UTC(2024, 0, 15, 10, 30, 0);
console.log(utcTimestamp);
2. 获取日期时间信息
const date = new Date("2024-01-15T10:30:45.123");
// 获取年、月、日
console.log(date.getFullYear()); // 2024(4位数年份)
console.log(date.getYear()); // 124(从1900开始的年数,已废弃)
console.log(date.getMonth()); // 0(0-11,0表示一月)
console.log(date.getDate()); // 15(1-31)
console.log(date.getDay()); // 1(0-6,0表示周日)
// 获取时间
console.log(date.getHours()); // 10(0-23)
console.log(date.getMinutes()); // 30(0-59)
console.log(date.getSeconds()); // 45(0-59)
console.log(date.getMilliseconds()); // 123(0-999)
// UTC时间(世界标准时间)
console.log(date.getUTCFullYear()); // 2024
console.log(date.getUTCMonth()); // 0
console.log(date.getUTCDate()); // 15
console.log(date.getUTCHours()); // 2(根据时区计算)
console.log(date.getUTCMinutes()); // 30
console.log(date.getUTCSeconds()); // 45
console.log(date.getUTCMilliseconds()); // 123
// 时间戳
console.log(date.getTime()); // 毫秒时间戳
console.log(date.valueOf()); // 同getTime()
3. 设置日期时间
const date = new Date();
// 设置年月日
date.setFullYear(2024);
date.setMonth(0); // 0=一月
date.setDate(15);
// 设置时间
date.setHours(10);
date.setMinutes(30);
date.setSeconds(45);
date.setMilliseconds(123);
// 设置UTC时间
date.setUTCFullYear(2024);
date.setUTCMonth(0);
date.setUTCDate(15);
date.setUTCHours(10);
date.setUTCMinutes(30);
// 通过时间戳设置
date.setTime(1640995200000);
// 链式设置
date.setFullYear(2024).setMonth(0).setDate(15);
// 注意:set方法会修改原Date对象
console.log(date);
日期时间格式化
1. 内置格式化方法
const date = new Date("2024-01-15T10:30:45");
// 转换为字符串
console.log(date.toString()); // "Mon Jan 15 2024 10:30:45 GMT+0800 (中国标准时间)"
console.log(date.toDateString()); // "Mon Jan 15 2024"
console.log(date.toTimeString()); // "10:30:45 GMT+0800 (中国标准时间)"
// UTC时间字符串
console.log(date.toUTCString()); // "Mon, 15 Jan 2024 02:30:45 GMT"
console.log(date.toISOString()); // "2024-01-15T02:30:45.000Z"(ISO 8601)
console.log(date.toJSON()); // "2024-01-15T02:30:45.000Z"(用于JSON序列化)
// 本地化字符串
console.log(date.toLocaleString()); // "2024/1/15 10:30:45"
console.log(date.toLocaleDateString()); // "2024/1/15"
console.log(date.toLocaleTimeString()); // "10:30:45"
2. 高级本地化格式化
const date = new Date("2024-01-15T10:30:45");
// 中文格式化
console.log(date.toLocaleString("zh-CN")); // "2024/1/15 10:30:45"
console.log(
date.toLocaleString("zh-CN", {
year: "numeric",
month: "long",
day: "numeric",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
})
); // "2024年1月15日星期一 10:30:45"
// 美国英语格式化
console.log(
date.toLocaleString("en-US", {
dateStyle: "full",
timeStyle: "full",
})
); // "Monday, January 15, 2024 at 10:30:45 AM China Standard Time"
// 日期部分格式化选项
const options = {
// 年份
year: "numeric", // 2024
year: "2-digit", // 24
// 月份
month: "numeric", // 1
month: "2-digit", // 01
month: "long", // January
month: "short", // Jan
month: "narrow", // J
// 日
day: "numeric", // 15
day: "2-digit", // 15
// 星期
weekday: "long", // Monday
weekday: "short", // Mon
weekday: "narrow", // M
// 时间
hour: "numeric", // 10
hour: "2-digit", // 10
minute: "numeric", // 30
minute: "2-digit", // 30
second: "numeric", // 45
second: "2-digit", // 45
// 时区
timeZoneName: "long", // China Standard Time
timeZoneName: "short", // CST
// 小时制
hour12: true, // 12小时制(默认)
hour12: false, // 24小时制
// 简化选项
dateStyle: "full", // 完整日期格式
dateStyle: "long",
dateStyle: "medium",
dateStyle: "short",
timeStyle: "full", // 完整时间格式
timeStyle: "long",
timeStyle: "medium",
timeStyle: "short",
};
// 实用格式化示例
console.log(
date.toLocaleDateString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
})
); // "2024/01/15"
console.log(
date.toLocaleTimeString("zh-CN", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
})
); // "10:30:45"
// 时区转换
console.log(
date.toLocaleString("en-US", {
timeZone: "America/New_York",
})
); // "1/14/2024, 9:30:45 PM"
3. 自定义格式化
// 1. 基本格式化函数
function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
const pad = n => n.toString().padStart(2, "0");
const replacements = {
YYYY: date.getFullYear(),
YY: date.getFullYear().toString().slice(-2),
MM: pad(date.getMonth() + 1),
M: date.getMonth() + 1,
DD: pad(date.getDate()),
D: date.getDate(),
HH: pad(date.getHours()),
H: date.getHours(),
hh: pad(date.getHours() % 12 || 12),
h: date.getHours() % 12 || 12,
mm: pad(date.getMinutes()),
m: date.getMinutes(),
ss: pad(date.getSeconds()),
s: date.getSeconds(),
SSS: date.getMilliseconds().toString().padStart(3, "0"),
A: date.getHours() < 12 ? "AM" : "PM",
a: date.getHours() < 12 ? "am" : "pm",
ddd: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][date.getDay()],
dddd: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][
date.getDay()
],
};
return format.replace(
/YYYY|YY|MM|M|DD|D|HH|H|hh|h|mm|m|ss|s|SSS|A|a|ddd|dddd/g,
match => replacements[match]
);
}
const date = new Date("2024-01-15T10:30:45.123");
console.log(formatDate(date)); // "2024-01-15 10:30:45"
console.log(formatDate(date, "YYYY年MM月DD日 HH:mm")); // "2024年01月15日 10:30"
console.log(formatDate(date, "YYYY/MM/DD hh:mm A")); // "2024/01/15 10:30 AM"
console.log(formatDate(date, "dddd, MMMM D, YYYY")); // "Monday, 1 15, 2024"
// 2. 相对时间格式化
function formatRelativeTime(date, baseDate = new Date()) {
const diffInSeconds = Math.floor((baseDate - date) / 1000);
if (diffInSeconds < 60) return "刚刚";
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}分钟前`;
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}小时前`;
if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)}天前`;
if (diffInSeconds < 31536000) return `${Math.floor(diffInSeconds / 2592000)}个月前`;
return `${Math.floor(diffInSeconds / 31536000)}年前`;
}
const pastDate = new Date(Date.now() - 3 * 60 * 60 * 1000); // 3小时前
console.log(formatRelativeTime(pastDate)); // "3小时前"
// 3. Intl.DateTimeFormat(更现代的API)
const formatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "long",
day: "numeric",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZoneName: "long",
});
console.log(formatter.format(date)); // "2024年1月15日星期一 10:30:45 中国标准时间"
// 可重用的格式化器
const dateFormatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
});
const timeFormatter = new Intl.DateTimeFormat("zh-CN", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
console.log(`${dateFormatter.format(date)} ${timeFormatter.format(date)}`);
// "2024/01/15 10:30:45"
日期时间计算
1. 时间差计算
// 计算两个日期的时间差
function getTimeDifference(start, end = new Date()) {
const diff = Math.abs(end - start);
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const months = Math.floor(days / 30);
const years = Math.floor(days / 365);
return {
milliseconds: diff,
seconds: seconds,
minutes: minutes,
hours: hours,
days: days,
months: months,
years: years,
// 格式化输出
toString() {
if (years > 0) return `${years}年${months % 12}个月`;
if (months > 0) return `${months}个月${days % 30}天`;
if (days > 0) return `${days}天${hours % 24}小时`;
if (hours > 0) return `${hours}小时${minutes % 60}分钟`;
if (minutes > 0) return `${minutes}分钟${seconds % 60}秒`;
return `${seconds}秒`;
},
};
}
const start = new Date("2024-01-01");
const end = new Date("2024-01-15T10:30:00");
const diff = getTimeDifference(start, end);
console.log(diff.toString()); // "14天10小时"
console.log(diff.days); // 14
// 计算剩余时间
function getTimeRemaining(targetDate) {
const now = new Date();
const diff = targetDate - now;
if (diff <= 0) {
return { expired: true };
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return {
days,
hours,
minutes,
seconds,
totalSeconds: Math.floor(diff / 1000),
expired: false,
};
}
const target = new Date(Date.now() + 3 * 24 * 60 * 60 * 1000); // 3天后
console.log(getTimeRemaining(target));
2. 日期加减操作
// 日期加减函数
function addDays(date, days) {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
function addMonths(date, months) {
const result = new Date(date);
result.setMonth(result.getMonth() + months);
return result;
}
function addYears(date, years) {
const result = new Date(date);
result.setFullYear(result.getFullYear() + years);
return result;
}
function addHours(date, hours) {
return new Date(date.getTime() + hours * 60 * 60 * 1000);
}
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes * 60 * 1000);
}
// 使用示例
const today = new Date();
console.log(addDays(today, 7)); // 7天后
console.log(addMonths(today, 1)); // 1个月后
console.log(addYears(today, 1)); // 1年后
// 完整的日期操作库(简化版)
class DateCalculator {
constructor(date = new Date()) {
this.date = new Date(date);
}
add(value, unit) {
const units = {
years: v => this.date.setFullYear(this.date.getFullYear() + v),
months: v => this.date.setMonth(this.date.getMonth() + v),
days: v => this.date.setDate(this.date.getDate() + v),
hours: v => this.date.setHours(this.date.getHours() + v),
minutes: v => this.date.setMinutes(this.date.getMinutes() + v),
seconds: v => this.date.setSeconds(this.date.getSeconds() + v),
milliseconds: v => this.date.setTime(this.date.getTime() + v),
};
if (units[unit]) {
units[unit](../04-javascript/value);
}
return this;
}
subtract(value, unit) {
return this.add(-value, unit);
}
get() {
return new Date(this.date);
}
}
const calc = new DateCalculator();
const nextWeek = calc.add(7, "days").get();
const lastMonth = calc.subtract(1, "months").get();
3. 日期比较
// 比较两个日期
function compareDates(date1, date2) {
const d1 = new Date(date1);
const d2 = new Date(date2);
if (d1 < d2) return -1;
if (d1 > d2) return 1;
return 0;
}
// 检查日期是否在范围内
function isDateInRange(date, start, end) {
const d = new Date(date);
const s = new Date(start);
const e = new Date(end);
return d >= s && d <= e;
}
// 检查是否为同一天
function isSameDay(date1, date2) {
const d1 = new Date(date1);
const d2 = new Date(date2);
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
}
// 检查是否为工作日
function isWeekday(date) {
const day = new Date(date).getDay();
return day !== 0 && day !== 6; // 0=周日, 6=周六
}
// 检查是否为周末
function isWeekend(date) {
const day = new Date(date).getDay();
return day === 0 || day === 6;
}
// 获取日期的开始和结束时间
function getStartOfDay(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
return d;
}
function getEndOfDay(date) {
const d = new Date(date);
d.setHours(23, 59, 59, 999);
return d;
}
// 获取月份的开始和结束日期
function getStartOfMonth(date) {
const d = new Date(date);
d.setDate(1);
d.setHours(0, 0, 0, 0);
return d;
}
function getEndOfMonth(date) {
const d = new Date(date);
d.setMonth(d.getMonth() + 1);
d.setDate(0);
d.setHours(23, 59, 59, 999);
return d;
}
// 示例
const date = new Date();
console.log(isWeekday(date)); // true(如果是工作日)
console.log(getStartOfDay(date)); // 当天00:00:00.000
console.log(getEndOfMonth(date)); // 当月最后一天23:59:59.999
时区处理
1. 时区基础
// 获取当前时区
function getCurrentTimezone() {
// 方法1:使用Intl API
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// 方法2:从日期字符串提取
const date = new Date();
const timezoneStr = date.toString().match(/\(([^)]+)\)/)[1];
// 方法3:获取时区偏移
const offset = date.getTimezoneOffset(); // 分钟数
const hours = Math.abs(Math.floor(offset / 60));
const minutes = Math.abs(offset % 60);
const sign = offset > 0 ? "-" : "+";
return {
name: timezone,
displayName: timezoneStr,
offset: offset,
formatted: `UTC${sign}${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}`,
};
}
console.log(getCurrentTimezone());
// 时区转换
function convertTimezone(date, targetTimezone) {
// 使用Intl.DateTimeFormat进行转换
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: targetTimezone,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
const parts = formatter.formatToParts(date);
const partToValue = {};
parts.forEach(part => {
partToValue[part.type] = part.value;
});
return new Date(
`${partToValue.year}-${partToValue.month}-${partToValue.day}T${partToValue.hour}:${partToValue.minute}:${partToValue.second}`
);
}
const date = new Date();
console.log(convertTimezone(date, "America/New_York"));
console.log(convertTimezone(date, "Asia/Tokyo"));
// 列出所有时区
function listTimezones() {
return Intl.supportedValuesOf("timeZone");
}
console.log(listTimezones().slice(0, 10)); // 显示前10个时区
2. UTC 与本地时间转换
// 本地时间转UTC
function toUTC(date) {
return new Date(date.getTime() - date.getTimezoneOffset() * 60000);
}
// UTC转本地时间
function fromUTC(utcDate) {
return new Date(utcDate.getTime() + utcDate.getTimezoneOffset() * 60000);
}
// 创建指定时区的时间
function createDateInTimezone(year, month, day, hour, minute, timezone) {
// 创建UTC时间
const utcDate = new Date(Date.UTC(year, month, day, hour, minute));
// 使用Intl格式化
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: timezone,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
return formatter.format(utcDate);
}
// 计算时区偏移
function getTimezoneOffset(timezone, date = new Date()) {
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: timezone,
timeZoneName: "longOffset",
});
const parts = formatter.formatToParts(date);
const offsetPart = parts.find(part => part.type === "timeZoneName");
if (offsetPart) {
const match = offsetPart.value.match(/UTC([+-])(\d{2}):?(\d{2})?/);
if (match) {
const sign = match[1] === "+" ? 1 : -1;
const hours = parseInt(match[2]);
const minutes = match[3] ? parseInt(match[3]) : 0;
return sign * (hours * 60 + minutes); // 返回分钟数
}
}
return null;
}
// 示例
console.log(getTimezoneOffset("America/New_York")); // -300(分钟)
console.log(getTimezoneOffset("Asia/Shanghai")); // 480
日历与日期计算
1. 月份相关计算
// 获取月份天数
function getDaysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
// 获取月份的第一天是星期几
function getFirstDayOfMonth(year, month) {
return new Date(year, month, 1).getDay();
}
// 生成月份日历
function generateMonthCalendar(year, month) {
const daysInMonth = getDaysInMonth(year, month);
const firstDay = getFirstDayOfMonth(year, month);
const calendar = [];
let week = [];
// 填充前面的空格
for (let i = 0; i < firstDay; i++) {
week.push(null);
}
// 填充日期
for (let day = 1; day <= daysInMonth; day++) {
week.push(new Date(year, month, day));
if (week.length === 7) {
calendar.push(week);
week = [];
}
}
// 填充后面的空格
if (week.length > 0) {
while (week.length < 7) {
week.push(null);
}
calendar.push(week);
}
return calendar;
}
// 使用示例
const calendar = generateMonthCalendar(2024, 0); // 2024年1月
console.log(calendar);
// 判断是否为闰年
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
// 获取一年的天数
function getDaysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
// 计算两个日期之间的工作日天数
function getWorkingDays(start, end) {
const startDate = new Date(start);
const endDate = new Date(end);
let count = 0;
while (startDate <= endDate) {
const day = startDate.getDay();
if (day !== 0 && day !== 6) {
count++;
}
startDate.setDate(startDate.getDate() + 1);
}
return count;
}
2. 节日和特殊日期
// 计算复活节日期(西方算法)
function getEasterDate(year) {
const a = year % 19;
const b = Math.floor(year / 100);
const c = year % 100;
const d = Math.floor(b / 4);
const e = b % 4;
const f = Math.floor((b + 8) / 25);
const g = Math.floor((b - f + 1) / 3);
const h = (19 * a + b - d - g + 15) % 30;
const i = Math.floor(c / 4);
const k = c % 4;
const l = (32 + 2 * e + 2 * i - h - k) % 7;
const m = Math.floor((a + 11 * h + 22 * l) / 451);
const month = Math.floor((h + l - 7 * m + 114) / 31);
const day = ((h + l - 7 * m + 114) % 31) + 1;
return new Date(year, month - 1, day);
}
// 中国农历节日(简化版)
const lunarHolidays = {
春节: { month: 1, day: 1 },
元宵节: { month: 1, day: 15 },
端午节: { month: 5, day: 5 },
中秋节: { month: 8, day: 15 },
重阳节: { month: 9, day: 9 },
};
// 获取下一个节日
function getNextHoliday(date = new Date()) {
const holidays = {
元旦: new Date(date.getFullYear() + 1, 0, 1),
春节: getChineseNewYear(date.getFullYear()),
清明节: getQingmingDate(date.getFullYear()),
劳动节: new Date(date.getFullYear(), 4, 1),
端午节: getDragonBoatDate(date.getFullYear()),
中秋节: getMidAutumnDate(date.getFullYear()),
国庆节: new Date(date.getFullYear(), 9, 1),
};
let nextHoliday = null;
let minDiff = Infinity;
for (const [name, holidayDate] of Object.entries(holidays)) {
const diff = holidayDate - date;
if (diff > 0 && diff < minDiff) {
minDiff = diff;
nextHoliday = { name, date: holidayDate };
}
}
return nextHoliday;
}
// 计算中国农历节日(简化)
function getChineseNewYear(year) {
// 简化算法:春节通常在1月21日到2月20日之间
// 实际需要复杂的农历计算
return new Date(year, 1, 1); // 示例
}
性能优化与最佳实践
1. 避免重复创建 Date 对象
// 不好:每次循环都创建新的Date对象
function processDatesBad(dates) {
return dates.map(dateStr => {
const date = new Date(dateStr);
return date.toLocaleDateString();
});
}
// 好:重用formatter
function processDatesGood(dates) {
const formatter = new Intl.DateTimeFormat("zh-CN");
return dates.map(dateStr => {
const date = new Date(dateStr);
return formatter.format(date);
});
}
// 更好:缓存计算结果
class DateCache {
constructor() {
this.cache = new Map();
this.formatter = new Intl.DateTimeFormat("zh-CN");
}
format(dateStr) {
if (!this.cache.has(dateStr)) {
const date = new Date(dateStr);
this.cache.set(dateStr, this.formatter.format(date));
}
return this.cache.get(dateStr);
}
}
2. 处理大量日期数据
// 使用时间戳进行计算
function processLargeDateSet(dates) {
// 转换为时间戳数组
const timestamps = dates.map(date => date.getTime());
// 对时间戳进行排序
timestamps.sort((a, b) => a - b);
// 计算平均值
const avgTimestamp = timestamps.reduce((sum, ts) => sum + ts, 0) / timestamps.length;
return new Date(avgTimestamp);
}
// 批量格式化日期
function batchFormatDates(dates, locale = "zh-CN") {
const formatter = new Intl.DateTimeFormat(locale);
return dates.map(date => formatter.format(date));
}
// 使用Web Workers处理大量日期计算
// main.js
const worker = new Worker("date-worker.js");
worker.postMessage({ dates: largeDateArray });
worker.onmessage = event => {
console.log("处理结果:", event.data);
};
// date-worker.js
self.onmessage = event => {
const dates = event.data.dates;
const results = dates.map(date => {
// 复杂的日期计算
return processDate(date);
});
self.postMessage(results);
};
3. 日期验证
// 验证日期字符串
function isValidDate(dateString) {
// 方法1:使用Date.parse
const timestamp = Date.parse(dateString);
return !isNaN(timestamp);
// 方法2:创建Date对象检查
const date = new Date(dateString);
return date instanceof Date && !isNaN(date.getTime());
}
// 验证日期范围
function isValidDateRange(start, end, minDays = 0, maxDays = 365) {
const startDate = new Date(start);
const endDate = new Date(end);
if (!isValidDate(start) || !isValidDate(end)) {
return false;
}
const diffTime = Math.abs(endDate - startDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays >= minDays && diffDays <= maxDays;
}
// 检查日期格式
function checkDateFormat(dateString, format = "YYYY-MM-DD") {
const patterns = {
"YYYY-MM-DD": /^\d{4}-\d{2}-\d{2}$/,
"YYYY/MM/DD": /^\d{4}\/\d{2}\/\d{2}$/,
"YYYY-MM-DD HH:mm:ss": /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
ISO: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z?$/,
};
const pattern = patterns[format];
return pattern ? pattern.test(dateString) : false;
}
现代日期时间库(替代方案)
1. 使用 date-fns(流行的轻量级库)
// 使用date-fns进行日期操作
import {
format,
formatDistance,
formatRelative,
addDays,
addMonths,
isSameDay,
differenceInDays,
parseISO,
} from "date-fns";
import { zhCN } from "date-fns/locale";
const date = new Date();
// 格式化
console.log(format(date, "yyyy-MM-dd")); // "2024-01-15"
console.log(format(date, "PPPP", { locale: zhCN })); // "2024年1月15日星期一"
// 相对时间
console.log(formatDistance(date, new Date(), { locale: zhCN })); // "不到 1 分钟"
// 日期计算
const nextWeek = addDays(date, 7);
const nextMonth = addMonths(date, 1);
// 日期比较
console.log(isSameDay(date, new Date())); // true
// 日期差
console.log(differenceInDays(nextWeek, date)); // 7
// 解析
const parsedDate = parseISO("2024-01-15T10:30:00");
2. 使用 Day.js(极简的 Moment.js 替代)
// 使用Day.js进行日期操作
import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.locale("zh-cn");
dayjs.extend(relativeTime);
const date = dayjs();
// 格式化
console.log(date.format("YYYY-MM-DD HH:mm:ss")); // "2024-01-15 10:30:45"
console.log(date.format("dddd, MMMM D, YYYY")); // "星期一, 一月 15, 2024"
// 相对时间
console.log(date.fromNow()); // "几秒前"
// 日期计算
const nextWeek = date.add(7, "day");
const nextMonth = date.add(1, "month");
// 日期查询
console.log(date.isSame(nextWeek, "day")); // false
console.log(date.isBefore(nextWeek)); // true
console.log(date.isAfter(nextWeek)); // false
// 获取时间差
const diff = date.diff(nextWeek, "day"); // -7
3. 使用 Temporal API(未来的标准)
// Temporal API(提案阶段,未来将成为标准)
// 目前需要polyfill
// 创建Temporal对象
const plainDate = Temporal.PlainDate.from("2024-01-15");
const plainTime = Temporal.PlainTime.from("10:30:45");
const zonedDateTime = Temporal.ZonedDateTime.from("2024-01-15T10:30:45+08:00[Asia/Shanghai]");
// 日期计算
const nextWeek = plainDate.add({ days: 7 });
const startOfMonth = plainDate.with({ day: 1 });
// 格式化
console.log(plainDate.toString()); // "2024-01-15"
console.log(plainDate.toLocaleString("zh-CN")); // "2024/1/15"
// 时区处理
const nyTime = zonedDateTime.withTimeZone("America/New_York");
// 时间差
const duration = plainDate.until(nextWeek);
console.log(duration.toString()); // "P7D"(7天)
实用工具函数集合
// 日期工具库
const DateUtils = {
// 格式化相关
format(date, pattern = "YYYY-MM-DD") {
const d = new Date(date);
const map = {
YYYY: d.getFullYear(),
MM: (d.getMonth() + 1).toString().padStart(2, "0"),
DD: d.getDate().toString().padStart(2, "0"),
HH: d.getHours().toString().padStart(2, "0"),
mm: d.getMinutes().toString().padStart(2, "0"),
ss: d.getSeconds().toString().padStart(2, "0"),
};
return pattern.replace(/YYYY|MM|DD|HH|mm|ss/g, match => map[match]);
},
// 人性化时间显示
humanize(date) {
const now = new Date();
const diff = now - new Date(date);
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (seconds < 60) return "刚刚";
if (minutes < 60) return `${minutes}分钟前`;
if (hours < 24) return `${hours}小时前`;
if (days < 7) return `${days}天前`;
if (days < 30) return `${Math.floor(days / 7)}周前`;
if (days < 365) return `${Math.floor(days / 30)}个月前`;
return `${Math.floor(days / 365)}年前`;
},
// 获取年龄
getAge(birthDate) {
const today = new Date();
const birth = new Date(birthDate);
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
age--;
}
return age;
},
// 获取星期几的中文名称
getChineseWeekday(date) {
const weekdays = ["日", "一", "二", "三", "四", "五", "六"];
return weekdays[new Date(date).getDay()];
},
// 检查是否为工作日
isWorkday(date) {
const d = new Date(date);
const day = d.getDay();
return day !== 0 && day !== 6; // 0=周日, 6=周六
},
// 获取当月工作日列表
getWorkdaysInMonth(year, month) {
const workdays = [];
const daysInMonth = new Date(year, month + 1, 0).getDate();
for (let day = 1; day <= daysInMonth; day++) {
const date = new Date(year, month, day);
if (this.isWorkday(date)) {
workdays.push(date);
}
}
return workdays;
},
// 计算两个日期之间的工作日
countWorkdaysBetween(start, end) {
const startDate = new Date(start);
const endDate = new Date(end);
let count = 0;
while (startDate <= endDate) {
if (this.isWorkday(startDate)) {
count++;
}
startDate.setDate(startDate.getDate() + 1);
}
return count;
},
// 获取季度
getQuarter(date) {
const month = new Date(date).getMonth();
return Math.floor(month / 3) + 1;
},
// 获取季度开始和结束日期
getQuarterRange(date) {
const d = new Date(date);
const year = d.getFullYear();
const quarter = this.getQuarter(date);
const startMonth = (quarter - 1) * 3;
return {
start: new Date(year, startMonth, 1),
end: new Date(year, startMonth + 3, 0, 23, 59, 59, 999),
};
},
};
// 使用示例
console.log(DateUtils.format(new Date(), "YYYY年MM月DD日")); // "2024年01月15日"
console.log(DateUtils.humanize(new Date(Date.now() - 3600000))); // "1小时前"
console.log(DateUtils.getAge("1990-01-01")); // 34
console.log(DateUtils.getChineseWeekday(new Date())); // "一"
console.log(DateUtils.getQuarter(new Date())); // 1