JavaScript学习笔记:8.日期和时间

JavaScript学习笔记:8.日期和时间

上一篇搞定了数字和字符串这两个"基础工具人",这一篇咱们来解锁JS的"时间管理大师"------日期和时间处理。如果说数字是"记账本",字符串是"日记本",那日期时间就是JS的"日程表",不管是做倒计时、预约功能,还是数据统计,都离不开它。

但JS的日期处理堪称"坑王聚集地":月份从0开始、时区错乱、字符串解析兼容问题,新手很容易写出让"12月变成11月""本地时间和UTC时间对不上"的bug。今天就用"生活化场景+踩坑实录"的方式,把Date对象的用法、坑点、实战技巧讲透,让你轻松搞定各种时间需求,再也不用对着代码挠头~

一、先搞懂:JS没有"日期类型",只有Date对象

首先明确一个核心知识点:JavaScript 压根没有专门的"日期数据类型"!所有日期和时间的处理,全靠内置的Date对象。它就像一个"时间工具箱",把时间存储为"自1970年1月1日00:00:00 UTC(纪元时间)以来的毫秒数"------这串数字叫时间戳,是时间的"唯一身份证",也是跨平台、跨时区处理时间的关键。

1. 创建Date对象:四种常用方式

创建Date对象就像"召唤时间管家",有四种常用姿势,按需选择:

js 复制代码
// 姿势1:无参数 → 获取当前时间(本地时区)
const now = new Date();
console.log(now); // 输出类似:2025-08-20T10:30:00.000Z(UTC时间)或本地时间格式

// 姿势2:传入时间戳(毫秒数) → 按时间戳创建
const timestamp = 1750000000000;
const dateByTs = new Date(timestamp);
console.log(dateByTs); // 对应时间戳的日期

// 姿势3:传入日期字符串 → 解析字符串(推荐格式:YYYY-MM-DDTHH:mm:ss.sssZ)
const dateByStr = new Date("2025-12-25T09:30:00");
console.log(dateByStr); // 2025年12月25日09:30:00(注意:字符串格式不规范会解析失败)

// 姿势4:传入整数参数 → 年, 月(0-11), 日, 时, 分, 秒
const dateByNum = new Date(2025, 11, 25, 9, 30, 0);
console.log(dateByNum); // 2025年12月25日09:30:00(重点:月份是0开始!)
避坑第一弹:月份从0开始,JS的"时间小癖好"

这是最经典的坑!JS的月份是0=1月,1=2月,...,11=12月,相当于"月份值=实际月份-1"。新手很容易把12月写成12,结果变成次年1月:

js 复制代码
// 反面例子:想创建12月,却写成12,实际是次年1月
const wrongDate = new Date(2025, 12, 25);
console.log(wrongDate.getMonth()); // 0(对应1月,翻车!)

// 正面例子:12月对应11
const rightDate = new Date(2025, 11, 25);
console.log(rightDate.getMonth()); // 11(正确)

二、核心方法:Date对象的"时间操作手册"

Date对象的方法分四大类:get(获取时间)、set(设置时间)、to(转换为字符串)、parse(解析字符串)。重点记高频方法,不用死记所有。

1. get系列:获取时间的"精准工具"

用于从Date对象中提取年、月、日、时、分、秒,核心方法如下(区分本地时间和UTC时间):

方法 作用 范围/说明
getFullYear() 获取年份(4位数) 如2025(推荐,替代getYear()
getMonth() 获取月份(本地时间) 0-11(记得+1才是实际月份)
getDate() 获取日期(本地时间) 1-31(月份中的第几天,不是星期!)
getDay() 获取星期(本地时间) 0-6(0=周日,6=周六)
getHours() 获取小时(本地时间) 0-23(24小时制)
getMinutes() 获取分钟 0-59
getSeconds() 获取秒 0-59
getTime() 获取时间戳(毫秒数) 核心方法,跨时区对比的关键
getUTC*() 获取UTC时间(如getUTCMonth() 与本地时间方法对应,不受时区影响
实用示例:获取当前日期的"年-月-日 星期"
js 复制代码
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1; // 月份+1
const date = now.getDate();
const week = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"][now.getDay()];

console.log(`${year}年${month}月${date}日 ${week}`); // 输出:2025年8月20日 周三(示例)

2. set系列:修改时间的"调整工具"

用于修改Date对象的时间,方法和get系列对应,修改后会直接改变原对象:

js 复制代码
const date = new Date(2025, 11, 25); // 2025-12-25

// 修改年份为2026
date.setFullYear(2026);
console.log(date.getFullYear()); // 2026

// 修改月份为3(对应4月)
date.setMonth(3);
console.log(date.getMonth() + 1); // 4

// 修改日期为10
date.setDate(10);
console.log(date.getDate()); // 10

// 最终日期:2026-04-10
避坑第二弹:set方法会"自动进位"

比如给日期设为32,会自动进位到下个月;给小时设为25,会进位到第二天:

js 复制代码
const date = new Date(2025, 11, 25); // 2025-12-25

// 日期设为32,自动进位到2026年1月1日
date.setDate(32);
console.log(date); // 2026-01-01(正确进位,不是报错!)

3. 时间戳:跨时区处理的"万能钥匙"

时间戳是"自纪元时间以来的毫秒数",不受时区、格式影响,是处理时间的"统一标准",核心用法:

js 复制代码
// 1. 获取当前时间戳(三种方式,推荐前两种)
const ts1 = new Date().getTime();
const ts2 = Date.now(); // ES5+,更简洁
const ts3 = +new Date(); // 隐式转换,简洁但可读性差

// 2. 时间戳转Date对象
const date = new Date(ts1);

// 3. 两个日期对比(用时间戳相减)
const date1 = new Date(2025, 11, 25);
const date2 = new Date(2025, 11, 30);
const diffMs = date2.getTime() - date1.getTime(); // 时间差(毫秒)
const diffDays = diffMs / (1000 * 60 * 60 * 24); // 转换为天数
console.log(diffDays); // 5(正确)
实战场景:计算今年剩余天数
js 复制代码
function getDaysLeftInYear() {
  const today = new Date();
  const endOfYear = new Date(today.getFullYear(), 11, 31, 23, 59, 59); // 当年12月31日23:59:59
  const diffMs = endOfYear.getTime() - today.getTime();
  return Math.ceil(diffMs / (1000 * 60 * 60 * 24)); // 向上取整,避免小数天
}

console.log(getDaysLeftInYear()); // 输出今年剩余天数(示例:130)

4. 字符串解析与转换:别踩"格式兼容坑"

(1)Date对象转字符串:to系列方法

用于将Date对象转为不同格式的字符串,按需选择:

js 复制代码
const date = new Date(2025, 11, 25, 9, 30, 0);

// 1. 标准格式(UTC):2025-12-25T01:30:00.000Z(带时区)
console.log(date.toISOString());

// 2. 本地时间字符串:2025/12/25 09:30:00(根据本地时区)
console.log(date.toLocaleString());

// 3. 自定义格式(推荐,避免兼容性问题)
function formatDate(date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0"); // 补0成两位
  const day = String(date.getDate()).padStart(2, "0");
  const hour = String(date.getHours()).padStart(2, "0");
  const minute = String(date.getMinutes()).padStart(2, "0");
  return `${year}-${month}-${day} ${hour}:${minute}`;
}
console.log(formatDate(date)); // 2025-12-25 09:30(自定义格式,兼容所有环境)
(2)字符串转Date对象:Date.parse()

解析日期字符串为时间戳,再转Date对象(推荐用标准格式,避免兼容问题):

js 复制代码
// 推荐格式:YYYY-MM-DDTHH:mm:ss(兼容所有浏览器)
const ts = Date.parse("2025-12-25T09:30:00");
const date = new Date(ts);
console.log(date); // 2025-12-25 09:30:00

// 避坑:非标准格式可能解析失败(如"2025/12/25"在部分浏览器可能有问题)
const wrongTs = Date.parse("2025/12/25");
console.log(wrongTs); // 可能返回NaN,不推荐!
避坑第三弹:时区导致的"日期偏移"

如果字符串不带时区标识(如Z表示UTC),JS会按本地时区解析,可能导致日期"差一天":

js 复制代码
// 字符串不带时区,按本地时区解析
const date1 = new Date("2025-12-25");
console.log(date1.toISOString()); // 可能输出2025-12-24T16:00:00.000Z(本地时区比UTC晚8小时)

// 带Z标识,按UTC解析
const date2 = new Date("2025-12-25T00:00:00Z");
console.log(date2.toISOString()); // 2025-12-25T00:00:00.000Z(正确)

三、常见实战场景:直接套用不翻车

1. 场景1:日期格式化(最常用)

将Date对象转为"YYYY-MM-DD HH:mm:ss"格式,兼容所有环境:

js 复制代码
function formatDateTime(date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hour = String(date.getHours()).padStart(2, "0");
  const minute = String(date.getMinutes()).padStart(2, "0");
  const second = String(date.getSeconds()).padStart(2, "0");
  return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

// 调用
const now = new Date();
console.log(formatDateTime(now)); // 2025-08-20 14:30:25(示例)

2. 场景2:倒计时功能(如活动结束倒计时)

js 复制代码
function countdownTo(targetDateStr) {
  const targetTs = new Date(targetDateStr).getTime();
  
  setInterval(() => {
    const nowTs = Date.now();
    const diffMs = targetTs - nowTs;
    
    if (diffMs <= 0) {
      console.log("活动结束!");
      return;
    }
    
    // 转换为天、时、分、秒
    const days = Math.floor(diffMs / (1000 * 60 * 60 * 24));
    const hours = Math.floor((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
    const seconds = Math.floor((diffMs % (1000 * 60)) / 1000);
    
    console.log(`倒计时:${days}天${hours}时${minutes}分${seconds}秒`);
  }, 1000);
}

// 调用:倒计时到2025年12月25日00:00:00
countdownTo("2025-12-25T00:00:00Z");

3. 场景3:判断两个日期是否是同一天

js 复制代码
function isSameDay(date1, date2) {
  return (
    date1.getFullYear() === date2.getFullYear() &&
    date1.getMonth() === date2.getMonth() &&
    date1.getDate() === date2.getDate()
  );
}

// 调用
const dateA = new Date(2025, 11, 25);
const dateB = new Date(2025, 11, 25, 18, 30);
const dateC = new Date(2025, 11, 26);
console.log(isSameDay(dateA, dateB)); // true(同一天)
console.log(isSameDay(dateA, dateC)); // false(不同天)

四、核心避坑总结:时间处理的"生存法则"

  1. 记住月份从0开始:实际月份 = getMonth() + 1,设置时 = 实际月份 - 1。
  2. 优先用时间戳对比:跨时区、跨格式对比时间,直接用getTime()取时间戳相减,避免时区干扰。
  3. 字符串用标准格式:解析字符串时用"YYYY-MM-DDTHH:mm:ssZ",避免兼容性问题。
  4. 警惕时区偏移:不带时区的字符串会按本地时区解析,可能导致日期差一天,重要场景带Z标识。
  5. 自定义格式化:别依赖toLocaleString()(不同浏览器格式可能不同),自己写格式化函数更靠谱。

五、结尾:时间处理,稳字当头

JS的日期时间处理看似复杂,实则核心就三点:掌握Date对象的创建和常用方法、避开月份和时区的坑、用时间戳统一处理跨场景需求。只要记住这些,日常开发中的时间格式化、倒计时、日期对比等需求都能轻松搞定。

相关推荐
梵尔纳多2 小时前
electron 安装
前端·javascript·electron
暗然而日章2 小时前
C++基础:Stanford CS106L学习笔记 10 函数模板(Function Templates)
c++·笔记·学习
swan4162 小时前
SCAU期末笔记 - 实时计算框架章末实验
笔记
zyq~2 小时前
【课堂笔记】统计
笔记·概率论
蒙奇D索大2 小时前
【数据结构】考研408|从B树到B+树:多路平衡的优化形态与数据库索引基石
数据结构·笔记·b树·学习·考研
不会代码的小猴2 小时前
C++的第十五天笔记
数据结构·c++·笔记
2401_834517072 小时前
AD学习笔记-32 PCB尺寸标注与边缘测量
笔记·学习
心.c2 小时前
初步了解Next.js
开发语言·前端·javascript·js