精通JavaScript日期处理:从格式到计算的完整指南

一、JavaScript日期对象基础操作

JavaScript中的Date对象是处理日期时间的核心,我们先从基础构造方法开始讲解:

// 获取当前时间
const now = new Date();

// 通过时间戳创建
const timestamp = 1622505600000;
const dateFromTimestamp = new Date(timestamp);

// 通过日期字符串创建(注意浏览器兼容性)
const dateFromString = new Date("2023-07-01T08:00:00");

// 通过参数构造
const specificDate = new Date(2023, 6, 1, 8, 30, 15); // 月份从0开始

常用获取方法:

console.log(now.getFullYear());  // 2023
console.log(now.getMonth() + 1); // 7(月份需要+1)
console.log(now.getDate());      // 具体日期
console.log(now.getHours());     // 时
console.log(now.getMinutes());   // 分
console.log(now.getSeconds());   // 秒
console.log(now.getMilliseconds());// 毫秒
console.log(now.getDay());       // 星期几(0-6)

二、日期格式化高级技巧

2.1 原生格式化方法

// 本地化日期格式
console.log(now.toLocaleDateString('zh-CN')); // 2023/7/1
console.log(now.toLocaleTimeString('en-US')); // 8:00:00 AM

// ISO标准格式
console.log(now.toISOString()); // 2023-07-01T00:00:00.000Z

2.2 自定义格式化函数

实现一个通用的格式化工具函数:

function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
  const pad = (n) => n.toString().padStart(2, '0');
  
  return format
    .replace(/YYYY/g, date.getFullYear())
    .replace(/MM/g, pad(date.getMonth() + 1))
    .replace(/DD/g, pad(date.getDate()))
    .replace(/HH/g, pad(date.getHours()))
    .replace(/mm/g, pad(date.getMinutes()))
    .replace(/ss/g, pad(date.getSeconds()))
    .replace(/SSS/g, date.getMilliseconds().toString().padStart(3, '0'));
}

// 使用示例
console.log(formatDate(now)); // 2023-07-01 08:30:15
console.log(formatDate(now, 'YYYY年MM月DD日')); // 2023年07月01日

2.3 复杂格式处理

处理季度、星期等特殊格式:

function advancedFormat(date, format) {
  const quarter = Math.ceil((date.getMonth() + 1) / 3);
  const weekMap = ['日', '一', '二', '三', '四', '五', '六'];
  
  return format
    .replace(/Q/g, quarter)
    .replace(/WWW/g, weekMap[date.getDay()])
    .replace(/W{1,2}/g, date.getDay() + 1);
}

console.log(advancedFormat(now, 'YYYY-Q季度 星期WWW')); // 2023-3季度 星期六

三、日期计算完全指南

3.1 基础日期计算

// 日期加减(毫秒级计算)
function dateAdd(date, interval, value) {
  const map = {
    y: 'FullYear',
    M: 'Month',
    d: 'Date',
    h: 'Hours',
    m: 'Minutes',
    s: 'Seconds'
  };
  
  const clone = new Date(date);
  clone[`set${map[interval]}`](clone[`get${map[interval]}`]() + value);
  return clone;
}

// 示例:加3天
const newDate = dateAdd(new Date(), 'd', 3);

3.2 复杂日期计算

处理月末边界情况:

function addMonths(date, months) {
  const newDate = new Date(date);
  const currentDay = newDate.getDate();
  
  newDate.setMonth(newDate.getMonth() + months);
  if (newDate.getDate() !== currentDay) {
    newDate.setDate(0); // 自动调整到上个月最后一天
  }
  return newDate;
}

// 测试1月31日加1个月
const testDate = new Date(2023, 0, 31);
console.log(addMonths(testDate, 1)); // 2023-02-28

3.3 日期差计算

精确计算日期差异:

function dateDiff(start, end, unit = 'd') {
  const diff = end - start;
  const units = {
    y: 31536000000,
    M: 2628000000,
    w: 604800000,
    d: 86400000,
    h: 3600000,
    m: 60000,
    s: 1000
  };
  
  return Math.floor(diff / units[unit]);
}

// 计算两个日期相差天数
const start = new Date(2023, 6, 1);
const end = new Date(2023, 6, 15);
console.log(dateDiff(start, end)); // 14

四、时区处理与国际化

4.1 时区转换

function convertTimezone(date, targetTimezone) {
  const utc = date.getTime() + (date.getTimezoneOffset() * 60000);
  return new Date(utc + (3600000 * targetTimezone));
}

// 北京时间转纽约时间
const beijingTime = new Date();
const newYorkTime = convertTimezone(beijingTime, -4);

4.2 国际化显示

const options = {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  timeZoneName: 'short'
};

console.log(new Date().toLocaleString('en-US', options));
// "July 1, 2023 at 08:30 AM EDT"

五、性能优化与最佳实践

5.1 日期操作性能对比

// 测试10万次日期创建
console.time('Date creation');
for (let i = 0; i < 100000; i++) {
  new Date();
}
console.timeEnd('Date creation'); // ≈15ms

5.2 内存优化技巧

// 使用时间戳缓存
const timestampCache = Date.now();

// 需要时再转换
function getCachedDate() {
  return new Date(timestampCache);
}

六、实战应用案例

6.1 日历组件核心逻辑

function generateCalendar(year, month) {
  const firstDay = new Date(year, month, 1);
  const lastDay = new Date(year, month + 1, 0);
  const calendar = [];
  
  // 生成日期矩阵
  let current = new Date(firstDay);
  current.setDate(current.getDate() - current.getDay());
  
  while (current <= lastDay || calendar.length < 6) {
    const week = [];
    for (let i = 0; i < 7; i++) {
      week.push(new Date(current));
      current.setDate(current.getDate() + 1);
    }
    calendar.push(week);
  }
  
  return calendar;
}

6.2 倒计时组件实现

class Countdown {
  constructor(endTime) {
    this.endTime = new Date(endTime);
    this.timer = null;
  }
  
  start(callback) {
    this.timer = setInterval(() => {
      const remaining = this.endTime - new Date();
      if (remaining <= 0) {
        this.stop();
        callback({ days: 0, hours: 0, minutes: 0, seconds: 0 });
        return;
      }
      
      const data = {
        days: Math.floor(remaining / 86400000),
        hours: Math.floor((remaining % 86400000) / 3600000),
        minutes: Math.floor((remaining % 3600000) / 60000),
        seconds: Math.floor((remaining % 60000) / 1000)
      };
      
      callback(data);
    }, 1000);
  }
  
  stop() {
    clearInterval(this.timer);
  }
}
正文到此结束
评论插件初始化中...
Loading...