知蛛网
  • 首页
  • 会员
  • 活动
  • 工作台

常见问题
活动
关于我们
联系我们
隐私协议
用户协议
会员协议
© 2026 知蛛网. 保留所有权利。
首页会员工作台我的
flynn@flynn
主页wiki简历作品集
目录
全部书籍
00-路线
  • 学习路线
  • 命名与写作规范
01-计算机基础
01-计算机网络
  • 互联网是如何工作的
  • HTTP协议
  • TCP/IP协议
  • 浏览器直接打开本地html文件,请求时的协议问题
02-浏览器原理
  • 浏览器是如何渲染页面的
  • 浏览器是如何渲染页面的
  • 面试之浏览器
03-操作系统
  • 进程与线程
  • 内存管理与虚拟内存
  • IO 模型与多路复用
  • 文件系统与页缓存
04-数据结构与算法
  • 数组与链表
  • 栈与队列
  • 哈希表
  • 树与堆
  • 基础数据结构
01-基础数据结构
02-高级算法
  • 排序算法
  • 二分查找
  • 递归与回溯
  • 动态规划
  • 双指针与滑动窗口
03-leetcode刷题
02-前端核心
01-web开发
  • Web 和 Web 标准
  • web 入门
  • web 开发
  • URL
  • 域名
  • Web服务器
  • 命令行
  • 工作流程和流程
  • 超链接
  • 浏览器指纹
02-html
  • HTML基础语法
  • HTML 概述
  • HTML 发展史
  • HTML调试
  • HTML标题与段落
  • 文本格式化
  • 强调与重要性
  • 块级元素和内联元素
  • 列表
  • 区块
  • 语义元素
  • 页面结构化和语义化
  • 超链接
  • 相对路径和绝对路径
  • 图片
  • 表格
  • 表单和按钮
  • 多媒体
  • 视频/音频
  • HTML 头部
  • HTML 字符集
  • HTML颜色
  • HTML 语言代码
  • HTML 国家/地区
  • Emoji (表情符号)
  • HTML 标签简写及全称 |
  • SVG
  • Canvas 2D
  • Canvas 3D
  • 框架 `<iframe>`
  • HTML 拖放
  • HTML5 Geolocation(地理定位)
  • Web 存储
  • HTML URL 编码
  • MathML
  • 远程图片资源在自己网站中无法展示问题
03-css
  • CSS简介
  • CSS 语法
  • CSS 创建
  • CSS 发展史
  • CSS 浏览器支持
  • CSS 选择器
  • CSS `!important` 规则
  • css颜色
  • CSS 文本格式
  • CSS 盒子模型
  • CSS 尺寸
  • CSS 内边距
  • CSS 外边距
  • CSS 边框
  • CSS 轮廓
  • CSS 背景(background)
  • CSS 溢出
  • CSS 文档流
  • CSS 显示和可见性
  • CSS 浮动
  • CSS 定位
  • CSS 对齐方式
  • CSS 网页布局
  • CSS 多列布局(CSS Multi-column Layout)
  • CSS 透明度
  • CSS 响应式设计(Responsive Design)
  • CSS 媒体查询
  • CSS 列表
  • CSS 表格
  • CSS 表单
  • CSS 链接
  • CSS 用户界面
  • CSS 计数器
  • CSS 过渡
  • CSS 动画
  • CSS 2D 转换
  • CSS 3D 转换
  • CSS 变量(CSS Custom Properties)
  • CSS 原生嵌套(CSS Nesting)
  • CSS 函数(CSS Functions)
04-javascript
  • 什么是 JavaScript?
  • 编程范式(Programming Paradigm)
  • 什么是范式?
  • ECMAScript 规范
  • 什么是语法糖
  • 开发环境搭建
  • 什么是堆和栈?
  • 什么是执行上下文
  • JavaScript 垃圾回收机制
  • 作业队列与事件循环
  • 深拷贝和浅拷贝
  • 语法与类型
  • 字面量
  • 控制流与错误处理
  • 循环与迭代
  • 函数
  • 表达式与运算符
  • 数字和字符串
  • 表达日期与时间
  • 正则表达式
  • 索引集合类
  • 带键的集合
  • 对象
  • 类
  • Promise
  • async/await
  • 迭代器和生成器
  • 国际化
  • 模块
  • 资源管理
  • 属性的可枚举性和所有权
  • 闭包
  • 继承与原型链
  • 元编程
  • 内存管理
  • 内置对象
  • arguments 对象
  • BOM 对象(浏览器对象模型)
  • DOM 对象(文档对象模型)
  • bind、apply、call的区别
  • new 操作符
  • typeof 和 instanceof 的区别
  • HTML5 Web Workers
05-typescript
  • TypeScript 类型系统基础
  • 类型体操
03-框架与跨端
01-react
  • 开发环境搭建
  • JSX
  • 组件
  • 生命周期
  • Hooks
  • 组件通信
  • 状态管理
  • React 19 新特性
  • useCallback 闭包陷阱
  • 常用的性能优化操作
  • Firbe 架构
  • React 18 新特性
  • useRef
  • 基于umijs 4.0 搭建官网
  • react+vite本地开发,如何手机联调
  • React 实现谷歌登录
  • React 项目调起 WhatsApp
02-vue
  • vue 解决跨域请求
  • 在vue2使用TinyMCE富文本编辑器
  • 使用jszip 导出新闻
  • Vue 本地开发启用 https
  • 基于vue3+vite+ts+elementplus+pinia+axios搭建后台管理系统
03-react-native
  • iOS 开发环境(RN 0.72)
  • RN 原生模块(Native Module)
  • 查看Maven包的Java包名
  • 优化 APP 启动速度
  • 安全键盘
  • 启动图与 Icon 尺寸规范
  • RN如何生成/配置iOS的开发者证书和生产证书
  • 邓白氏编码
  • 微信开放平台配置Universal Link
  • 上架至Apple App Store
04-android
  • 开发环境搭建
  • Android项目目录结构
  • 认识Gradle
04-工程化
01-git
  • 如何解决已被git跟踪文件不在跟踪
  • git标签
  • Git报错: Failed to connect to github.com port 443 解决方案
  • Git 分支操作速查
02-构建工具
  • 构建工具原理与选型
02-webpack
  • webpack 核心概念与构建流程
  • webpack 性能优化
03-vite
  • vite 为什么快
  • vite 插件与生产构建
03-测试
  • 前端测试体系
04-部署
  • Nginx 反向代理解决跨域
  • SPA 刷新非首页报 404
05-docker
  • Docker 常用命令
  • docker-compose nginx配置ssl证书
  • Docker Desktop 升级后 docker-compose 命令找不到
06-性能优化
  • 前端性能优化体系
  • 背景 GIF 优化方案
07-微前端
  • 微前端实战(qiankun)
  • 微前端 · qiankun
01-qiankun
05-后端与数据
01-nodejs
  • Node 版本与依赖的 engines 冲突
  • Express 实现 Gmail 发信(邮箱验证码)
02-php
  • 浏览器保存新闻,发布到自有网站
  • [分布式] 浏览器保存新闻,发布到自有网站
  • 邮件发送,多账号轮询
  • nginx和php-fpm通信问题导致网站页面空白
03-python
  • macOS M1 芯片 如何安装 py 和 tkinter
  • tkinter 编写的程序如何打包成桌面软件
04-架构设计
  • 后台管理系统中角色管理、管理员管理、权限设置他们三者之间的关系
05-运维
  • redis启动失败
  • 实现自动备份宝塔项目及数据库到本地
  • 宝塔面板
01-宝塔
06-实战项目
  • 实战准备工作
02-项目记录
  • AI-Chat 模块技术文档
  • CRMChat 部署
07-面试专项
01-面试
  • 面试之自我介绍
  • CSS 面试
  • JS面试
  • React面试
  • Vue面试
  • RN 面试 · 题目清单
  • RN 面试 · 答案详解
  • RN 物流公司 · 题目清单
  • RN 物流公司 · 答案详解
  • Uniapp 面试
  • 带团队经验
12-react专项
  • 一个表格,某一行的某一列数据变动了,如何优化性能?
13-reactnative专项
  • RN 开发过程中,有遇到什么棘手的问题?你是如何解决的?
14-过往面试总结
  • 冷哥传媒 · 面试题
  • 沐腾科技 · 面试题
  • 字符频率排序
02-面试八股
  • 网络八股
  • 浏览器八股
  • 工程化八股
03-算法面试题
  • 前端高频手写题
  • 场景设计题
04-真实面试经历
  • 20251027 盾蓝科技 面试
  • 20251028 芝麻甜心 面试
08-工具
01-n8n
  • 初始n8n
  • 快速入门
  • 在宝塔中搭建n8n环境
  • n8n中常用节点
  • n8n和代码的区别
02-Trae
  • Figma MCP 配置指南
03-UI_UX_pro_max
  • UI_UX_pro_max的使用
04-开发环境
  • VMWare虚拟机安装
  • PowerShell 执行策略与编码设置
98-杂项
  • A股股票交易相关费用
99-手册
  • iOS 开发者账号申请流程及费用
  • 邓白氏编码申请及费用
  • App 推送通道申请及费用
  • App 开发收费项目清单
  • 注册AWS账号
  • 使用Amazon Polly实现文本转语音
  • Google 翻译 Key 申请与前端调用
  • 使用SmsForwarder转发短信

表达日期与时间

04-javascript2026/11/14

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"
上一篇数字和字符串
下一篇正则表达式
本页目录
Date 对象基础1. 创建 Date 对象2. 获取日期时间信息3. 设置日期时间日期时间格式化1. 内置格式化方法2. 高级本地化格式化3. 自定义格式化日期时间计算1. 时间差计算2. 日期加减操作3. 日期比较时区处理1. 时区基础2. UTC 与本地时间转换日历与日期计算1. 月份相关计算2. 节日和特殊日期性能优化与最佳实践1. 避免重复创建 Date 对象2. 处理大量日期数据3. 日期验证现代日期时间库(替代方案)1. 使用 date-fns(流行的轻量级库)2. 使用 Day.js(极简的 Moment.js 替代)3. 使用 Temporal API(未来的标准)实用工具函数集合

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