日期计算是日常生活和软件开发中最常见的需求之一。无论是计算项目工期、合同到期日、还款周期,还是简单地算算距离生日还有多少天,都需要精确的日期运算能力。本文将全面介绍日期计算的各种方法,涵盖 JavaScript、Python 和 Excel 中的实现方式,并提供可直接复制使用的代码示例。

TL;DR

场景 JavaScript Python Excel
两日期间隔天数 (date2 - date1) / 86400000 (date2 - date1).days =B1-A1
日期加天数 date.setDate(date.getDate() + n) date + timedelta(days=n) =A1+n
工作日计算 循环判断 getDay() numpy.busday_count() =NETWORKDAYS(A1,B1)
月份差 手动计算年月差 relativedelta =DATEDIF(A1,B1,"M")

需要快速计算?直接使用 QubitTool 日期计算器,在线即时获取结果,无需编写任何代码。

引言

日期计算看似简单,实际上充满了各种复杂性:不同月份的天数不同(28、29、30、31天)、闰年的存在、时区差异、夏令时切换等。这些因素使得手动计算日期极易出错。

在现代开发中,日期计算广泛应用于:

  • 项目管理:计算 Sprint 周期、里程碑间隔、交付倒计时
  • 金融系统:计息天数、还款周期、合同期限
  • 电商平台:促销倒计时、退货期限、会员到期提醒
  • 法律领域:诉讼时效、合同有效期、上诉期限
  • 日常生活:生日倒计时、旅行天数、怀孕预产期

掌握正确的日期计算方法,可以在各种场景中节省大量时间,避免计算错误。

如何计算两个日期之间的天数

计算两个日期之间的天数是最基本也是最常用的日期运算。核心思路是将两个日期转换为统一的数值表示,然后相减。

基本计算公式

日期间隔的计算原理非常直观:

code
间隔天数 = 结束日期 - 开始日期

关键在于如何将"日期"转换为可以相减的数值。不同的编程语言和工具采用不同的内部表示方式:

语言/工具 内部表示 单位
JavaScript Unix 时间戳 毫秒
Python datetime 对象 直接支持相减
Excel 序列号(自1900-01-01起)
Java Instant / LocalDate 纳秒 / 天

JavaScript 实现

在 JavaScript 中,Date 对象内部以毫秒级 Unix 时间戳存储时间。两个日期相减得到毫秒差,再除以每天的毫秒数即可得到天数。

javascript
function daysBetween(dateStr1, dateStr2) {
  const MS_PER_DAY = 1000 * 60 * 60 * 24;
  const date1 = new Date(dateStr1);
  const date2 = new Date(dateStr2);
  const diffMs = Math.abs(date2.getTime() - date1.getTime());
  return Math.floor(diffMs / MS_PER_DAY);
}

console.log(daysBetween('2026-01-01', '2026-04-01'));
// 90

console.log(daysBetween('2026-03-01', '2026-06-15'));
// 106

如果需要更精确的结果(避免夏令时影响),可以使用 UTC 方法:

javascript
function daysBetweenUTC(dateStr1, dateStr2) {
  const MS_PER_DAY = 86400000;
  const date1 = new Date(dateStr1 + 'T00:00:00Z');
  const date2 = new Date(dateStr2 + 'T00:00:00Z');
  return Math.abs(Math.round((date2 - date1) / MS_PER_DAY));
}

console.log(daysBetweenUTC('2024-01-01', '2024-12-31'));
// 365(2024是闰年,1月1日到12月31日为365天)

使用现代 Temporal API(Stage 3 提案,部分运行时已支持):

javascript
const date1 = Temporal.PlainDate.from('2026-01-01');
const date2 = Temporal.PlainDate.from('2026-04-01');
const diff = date1.until(date2, { largestUnit: 'day' });
console.log(diff.days);
// 90

Python 实现

Python 的 datetime 模块原生支持日期运算,使用起来更加简洁直观。

python
from datetime import date

date1 = date(2026, 1, 1)
date2 = date(2026, 4, 1)
delta = date2 - date1
print(delta.days)
# 90

计算更细粒度的时间差(包括年、月、日):

python
from dateutil.relativedelta import relativedelta
from datetime import date

date1 = date(2023, 3, 15)
date2 = date(2026, 7, 20)

diff = relativedelta(date2, date1)
print(f"{diff.years}{diff.months}个月{diff.days}天")
# 3年4个月5天

批量计算多组日期间隔:

python
from datetime import date

date_pairs = [
    (date(2026, 1, 1), date(2026, 6, 30)),
    (date(2026, 3, 1), date(2026, 3, 31)),
    (date(2025, 12, 25), date(2026, 1, 1)),
]

for start, end in date_pairs:
    days = (end - start).days
    print(f"{start}{end}: {days}天")

# 2026-01-01 → 2026-06-30: 180天
# 2026-03-01 → 2026-03-31: 30天
# 2025-12-25 → 2026-01-01: 7天

Excel 公式

Excel 中日期的内部表示是序列号(自 1900 年 1 月 1 日起的天数),因此日期运算非常直观。

方法一:直接相减

code
=B1-A1

其中 A1 为开始日期,B1 为结束日期。结果直接为天数。需要将单元格格式设置为"数值"而非"日期"。

方法二:使用 DATEDIF 函数

DATEDIF 是 Excel 中专用的日期差计算函数,支持按不同单位返回结果:

code
=DATEDIF(A1, B1, "D")    返回总天数
=DATEDIF(A1, B1, "M")    返回完整月数
=DATEDIF(A1, B1, "Y")    返回完整年数
=DATEDIF(A1, B1, "YM")   返回扣除年后的剩余月数
=DATEDIF(A1, B1, "MD")   返回扣除月后的剩余天数

方法三:使用 DAYS 函数

code
=DAYS(B1, A1)

DAYS 函数是 Excel 2013 及以后版本引入的,语法更清晰,参数顺序为 DAYS(结束日期, 开始日期)

实用示例:计算年龄

code
=DATEDIF(A1, TODAY(), "Y") & "岁" & DATEDIF(A1, TODAY(), "YM") & "个月"

👉 在线日期计算器 - 无需公式即刻计算

日期加减运算

日期加减运算用于在给定日期的基础上,向前或向后推算指定天数、月数或年数后的日期。这在计算截止日期、到期日、预产期等场景中非常实用。

日期加天数

JavaScript 实现

javascript
function addDays(dateStr, days) {
  const date = new Date(dateStr);
  date.setDate(date.getDate() + days);
  return date.toISOString().split('T')[0];
}

console.log(addDays('2026-04-01', 30));
// "2026-05-01"

console.log(addDays('2026-04-01', 90));
// "2026-06-30"

console.log(addDays('2026-04-01', 365));
// "2027-04-01"

Python 实现

python
from datetime import date, timedelta

start = date(2026, 4, 1)

print(start + timedelta(days=30))
# 2026-05-01

print(start + timedelta(days=90))
# 2026-06-30

print(start + timedelta(days=365))
# 2027-04-01

加月份或年份(使用 dateutil):

python
from datetime import date
from dateutil.relativedelta import relativedelta

start = date(2026, 1, 31)

print(start + relativedelta(months=1))
# 2026-02-28(自动处理月末)

print(start + relativedelta(years=1))
# 2027-01-31

print(start + relativedelta(months=3, days=15))
# 2026-05-15

日期减天数

日期减法与加法原理相同,只是使用负数。

JavaScript 实现

javascript
function subtractDays(dateStr, days) {
  const date = new Date(dateStr);
  date.setDate(date.getDate() - days);
  return date.toISOString().split('T')[0];
}

console.log(subtractDays('2026-04-01', 30));
// "2026-03-02"

console.log(subtractDays('2026-04-01', 90));
// "2026-01-01"

Python 实现

python
from datetime import date, timedelta

end = date(2026, 4, 1)

print(end - timedelta(days=30))
# 2026-03-02

print(end - timedelta(days=90))
# 2026-01-01

Excel 公式

code
=A1+30        在日期上加30天
=A1-30        在日期上减30天
=EDATE(A1,3)  在日期上加3个月
=EDATE(A1,-6) 在日期上减6个月

常见应用场景

场景 计算方式 示例
项目截止日期 开始日期 + 工期天数 4月1日 + 90天 = 6月30日
订阅到期日 订阅日期 + 订阅周期 1月15日 + 1年 = 次年1月15日
合同到期日 签约日期 + 合同期限 3月1日 + 6个月 = 9月1日
退货截止日 购买日期 + 退货期 3月20日 + 7天 = 3月27日
贷款还款日 放款日期 + 还款周期 每月相同日期
预产期计算 末次月经 + 280天 标准孕期40周

工作日计算:排除周末和节假日

在项目管理和商业场景中,通常需要计算的是"工作日"而非"日历天数"。工作日计算需要排除周末,有时还需要排除法定节假日。

什么是工作日

类型 包含范围 典型应用
日历天数 所有天(周一至周日) 合同期限、保质期
工作日 周一至周五(排除周末) 项目工期、交货周期
净工作日 工作日 - 法定假日 薪资计算、排班

一般规律:30个日历天 ≈ 22个工作日一年约有 250-252 个工作日

JavaScript 实现

javascript
function workdaysBetween(startStr, endStr) {
  const start = new Date(startStr);
  const end = new Date(endStr);
  let count = 0;
  const current = new Date(start);

  while (current <= end) {
    const dayOfWeek = current.getDay();
    if (dayOfWeek !== 0 && dayOfWeek !== 6) {
      count++;
    }
    current.setDate(current.getDate() + 1);
  }
  return count;
}

console.log(workdaysBetween('2026-04-01', '2026-04-30'));
// 22

添加公众假日排除功能:

javascript
function workdaysBetweenWithHolidays(startStr, endStr, holidays = []) {
  const start = new Date(startStr);
  const end = new Date(endStr);
  const holidaySet = new Set(holidays);
  let count = 0;
  const current = new Date(start);

  while (current <= end) {
    const dayOfWeek = current.getDay();
    const dateStr = current.toISOString().split('T')[0];
    if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidaySet.has(dateStr)) {
      count++;
    }
    current.setDate(current.getDate() + 1);
  }
  return count;
}

const holidays = ['2026-04-06', '2026-05-01'];
console.log(workdaysBetweenWithHolidays('2026-04-01', '2026-04-30', holidays));
// 21

计算 N 个工作日后的日期:

javascript
function addWorkdays(startStr, workdays) {
  const date = new Date(startStr);
  let added = 0;

  while (added < workdays) {
    date.setDate(date.getDate() + 1);
    const dayOfWeek = date.getDay();
    if (dayOfWeek !== 0 && dayOfWeek !== 6) {
      added++;
    }
  }
  return date.toISOString().split('T')[0];
}

console.log(addWorkdays('2026-04-01', 10));
// "2026-04-15"

Excel NETWORKDAYS 函数

Excel 提供了内置的工作日计算函数,非常强大且方便。

NETWORKDAYS 函数:计算两个日期之间的工作日数

code
=NETWORKDAYS(A1, B1)

排除自定义假日

code
=NETWORKDAYS(A1, B1, D1:D10)

其中 D1:D10 为节假日列表。

WORKDAY 函数:计算 N 个工作日后的日期

code
=WORKDAY(A1, 10)          从A1起10个工作日后的日期
=WORKDAY(A1, -5)          从A1起5个工作日前的日期
=WORKDAY(A1, 10, D1:D5)   排除自定义假日

NETWORKDAYS.INTL 函数:自定义周末定义

code
=NETWORKDAYS.INTL(A1, B1, "0000011")

第三个参数为7位字符串,每一位对应周一至周日,1 表示非工作日,0 表示工作日。"0000011" 表示周六和周日为非工作日(默认值)。

不同国家和地区的周末定义可能不同:

地区 周末 NETWORKDAYS.INTL 参数
大多数国家 周六、周日 "0000011"
中东部分国家 周五、周六 "0000110"
仅周日休息 周日 "0000001"

处理公众假日

各国法定节假日差异很大,处理公众假日通常需要维护一个假日列表。

Python 方案(使用 holidays 库):

python
import holidays
from datetime import date, timedelta

cn_holidays = holidays.China(years=2026)

def workdays_between(start, end, country_holidays):
    count = 0
    current = start
    while current <= end:
        if current.weekday() < 5 and current not in country_holidays:
            count += 1
        current += timedelta(days=1)
    return count

start = date(2026, 1, 1)
end = date(2026, 12, 31)
print(workdays_between(start, end, cn_holidays))

使用 NumPy 的高效方案

python
import numpy as np
from datetime import date

start = date(2026, 4, 1)
end = date(2026, 4, 30)
holidays = [np.datetime64('2026-04-06')]

workdays = np.busday_count(
    np.datetime64(start),
    np.datetime64(end),
    holidays=holidays
)
print(workdays)
# 21

跨时区的日期计算

当日期计算涉及不同时区时,问题会变得更加复杂。一个看似简单的"今天"在不同时区可能对应不同的日期。

UTC 与本地时间

UTC(协调世界时)是全球时间的基准。在进行跨时区的日期计算时,建议统一使用 UTC 时间进行计算,然后再转换为本地时间显示。

javascript
const now = new Date();
console.log(now.toISOString());
// "2026-04-01T08:30:00.000Z" (UTC)

console.log(now.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }));
// "2026/4/1 16:30:00" (北京时间 UTC+8)

console.log(now.toLocaleString('zh-CN', { timeZone: 'America/New_York' }));
// "2026/4/1 04:30:00" (纽约时间 UTC-4)
python
from datetime import datetime, timezone, timedelta

utc_now = datetime.now(timezone.utc)
print(utc_now.strftime('%Y-%m-%d %H:%M:%S %Z'))
# 2026-04-01 08:30:00 UTC

beijing_tz = timezone(timedelta(hours=8))
beijing_now = utc_now.astimezone(beijing_tz)
print(beijing_now.strftime('%Y-%m-%d %H:%M:%S'))
# 2026-04-01 16:30:00

常见陷阱

陷阱一:夏令时导致天数计算不准确

在实行夏令时(DST)的地区,一天并不总是精确的 24 小时。春季"向前拨"时一天只有 23 小时,秋季"向后拨"时一天有 25 小时。

javascript
const spring2026 = new Date('2026-03-08T00:00:00');
const afterSpring = new Date('2026-03-09T00:00:00');
const diffHours = (afterSpring - spring2026) / (1000 * 60 * 60);
// 在美国时区可能是23小时而非24小时

解决方案:使用 UTC 时间进行日期计算,避免夏令时影响。

javascript
function safeDaysBetween(dateStr1, dateStr2) {
  const d1 = new Date(dateStr1 + 'T00:00:00Z');
  const d2 = new Date(dateStr2 + 'T00:00:00Z');
  return Math.round((d2 - d1) / 86400000);
}

陷阱二:时区偏移导致日期"漂移"

当服务器和客户端处于不同时区时,同一个时间戳可能对应不同的日期。

javascript
const timestamp = 1743465600000;

const utcDate = new Date(timestamp).toISOString().split('T')[0];
// "2025-04-01"

const localDate = new Date(timestamp).toLocaleDateString('zh-CN', {
  timeZone: 'Pacific/Auckland'
});
// "2025/4/2" (新西兰时间已经是4月2日)

解决方案:在存储和传输日期时始终使用 ISO 8601 格式(包含时区信息),在显示时才转换为本地时间。

陷阱三:new Date() 的解析差异

不同浏览器对日期字符串的解析行为不一致:

javascript
new Date('2026-04-01')
// 在某些浏览器中解析为UTC,在其他浏览器中解析为本地时间

new Date('2026-04-01T00:00:00Z')
// 明确指定UTC,所有浏览器一致

new Date('2026-04-01T00:00:00+08:00')
// 明确指定时区,所有浏览器一致

最佳实践:始终使用明确的时区标识,避免依赖浏览器的默认解析行为。

更多关于时区的处理方法,可以参考 时间戳转换器 提供的跨时区转换功能。

不同场景下的日期计算

项目管理

在敏捷开发和项目管理中,精确的日期计算有助于合理安排任务和资源。

Sprint 规划

python
from datetime import date, timedelta

sprint_start = date(2026, 4, 1)
sprint_length = 14

sprint_end = sprint_start + timedelta(days=sprint_length - 1)
print(f"Sprint周期: {sprint_start}{sprint_end}")
# Sprint周期: 2026-04-01 → 2026-04-14

sprints = []
current = sprint_start
for i in range(6):
    end = current + timedelta(days=sprint_length - 1)
    sprints.append((i + 1, current, end))
    current = end + timedelta(days=1)

for num, start, end in sprints:
    print(f"Sprint {num}: {start}{end}")

里程碑跟踪

javascript
function milestoneTracker(milestones) {
  const today = new Date();
  return milestones.map(m => {
    const target = new Date(m.date);
    const daysLeft = Math.ceil((target - today) / 86400000);
    return {
      name: m.name,
      date: m.date,
      daysLeft,
      status: daysLeft < 0 ? '已过期' : daysLeft === 0 ? '今天' : `剩余${daysLeft}天`
    };
  });
}

const milestones = [
  { name: '需求评审', date: '2026-04-15' },
  { name: 'Alpha版本', date: '2026-05-30' },
  { name: '正式发布', date: '2026-07-01' }
];

console.log(milestoneTracker(milestones));

法律领域

法律场景中的日期计算往往需要极高的准确性,因为截止日期一旦错过,可能造成不可逆的后果。

诉讼时效计算

python
from datetime import date
from dateutil.relativedelta import relativedelta

incident_date = date(2024, 6, 15)

statute_3y = incident_date + relativedelta(years=3)
print(f"事件日期: {incident_date}")
print(f"3年诉讼时效到期: {statute_3y}")
# 事件日期: 2024-06-15
# 3年诉讼时效到期: 2027-06-15

today = date(2026, 4, 1)
remaining = (statute_3y - today).days
print(f"距到期还剩: {remaining}天")
# 距到期还剩: 440天

合同期限

python
from datetime import date
from dateutil.relativedelta import relativedelta

sign_date = date(2026, 4, 1)

contract_1y = sign_date + relativedelta(years=1) - relativedelta(days=1)
contract_3y = sign_date + relativedelta(years=3) - relativedelta(days=1)

print(f"签约日期: {sign_date}")
print(f"1年合同到期: {contract_1y}")
print(f"3年合同到期: {contract_3y}")
# 签约日期: 2026-04-01
# 1年合同到期: 2027-03-31
# 3年合同到期: 2029-03-31

renewal_notice = contract_1y - relativedelta(months=1)
print(f"续约提醒日: {renewal_notice}")
# 续约提醒日: 2027-02-28

个人生活

年龄精确计算

javascript
function calculateExactAge(birthDateStr) {
  const birth = new Date(birthDateStr);
  const today = new Date();

  let years = today.getFullYear() - birth.getFullYear();
  let months = today.getMonth() - birth.getMonth();
  let days = today.getDate() - birth.getDate();

  if (days < 0) {
    months--;
    const prevMonth = new Date(today.getFullYear(), today.getMonth(), 0);
    days += prevMonth.getDate();
  }

  if (months < 0) {
    years--;
    months += 12;
  }

  return { years, months, days };
}

const age = calculateExactAge('1995-08-15');
console.log(`${age.years}${age.months}个月${age.days}天`);

活动倒计时

javascript
function countdown(eventName, eventDateStr) {
  const event = new Date(eventDateStr);
  const now = new Date();
  const diffMs = event - now;

  if (diffMs < 0) {
    return `${eventName}已过去${Math.abs(Math.floor(diffMs / 86400000))}天`;
  }

  const days = Math.floor(diffMs / 86400000);
  const hours = Math.floor((diffMs % 86400000) / 3600000);
  const minutes = Math.floor((diffMs % 3600000) / 60000);

  return `距离${eventName}还有${days}${hours}小时${minutes}分钟`;
}

console.log(countdown('国庆节', '2026-10-01'));
console.log(countdown('元旦', '2027-01-01'));

预产期计算

python
from datetime import date, timedelta

last_period = date(2026, 1, 15)

due_date = last_period + timedelta(days=280)
print(f"末次月经: {last_period}")
print(f"预产期: {due_date}")
# 末次月经: 2026-01-15
# 预产期: 2026-10-22

today = date(2026, 4, 1)
weeks_pregnant = (today - last_period).days // 7
days_remaining = (due_date - today).days
print(f"当前孕周: 第{weeks_pregnant}周")
print(f"距预产期: {days_remaining}天")
# 当前孕周: 第11周
# 距预产期: 204天

金融领域

计息天数(ACT/365 方法)

python
from datetime import date

deposit_date = date(2026, 1, 1)
maturity_date = date(2027, 1, 1)
principal = 100000
annual_rate = 0.035

days = (maturity_date - deposit_date).days
interest = principal * annual_rate * days / 365

print(f"存款本金: ¥{principal:,.2f}")
print(f"年利率: {annual_rate * 100}%")
print(f"计息天数: {days}天")
print(f"到期利息: ¥{interest:,.2f}")
# 存款本金: ¥100,000.00
# 年利率: 3.5%
# 计息天数: 365天
# 到期利息: ¥3,500.00

还款计划表

python
from datetime import date
from dateutil.relativedelta import relativedelta

loan_date = date(2026, 4, 1)
loan_amount = 500000
annual_rate = 0.0388
term_months = 360

monthly_rate = annual_rate / 12
monthly_payment = loan_amount * monthly_rate * (1 + monthly_rate) ** term_months / ((1 + monthly_rate) ** term_months - 1)

print(f"贷款金额: ¥{loan_amount:,.2f}")
print(f"年利率: {annual_rate * 100}%")
print(f"贷款期限: {term_months // 12}年")
print(f"月供: ¥{monthly_payment:,.2f}")
print()

balance = loan_amount
for i in range(1, 7):
    interest = balance * monthly_rate
    principal_part = monthly_payment - interest
    balance -= principal_part
    payment_date = loan_date + relativedelta(months=i)
    print(f"第{i}期 ({payment_date}): 月供¥{monthly_payment:,.2f} = 本金¥{principal_part:,.2f} + 利息¥{interest:,.2f} | 余额¥{balance:,.2f}")

信用卡账单周期

python
from datetime import date
from dateutil.relativedelta import relativedelta

statement_date = date(2026, 4, 5)
payment_due = statement_date + relativedelta(days=20)
next_statement = statement_date + relativedelta(months=1)

print(f"账单日: {statement_date}")
print(f"还款日: {payment_due}")
print(f"下期账单日: {next_statement}")
# 账单日: 2026-04-05
# 还款日: 2026-04-25
# 下期账单日: 2026-05-05

日期计算中的闰年处理

闰年是日期计算中必须考虑的因素。闰年的 2 月有 29 天,而平年的 2 月只有 28 天。

闰年判断规则

  1. 能被 4 整除的年份是闰年
  2. 能被 100 整除但不能被 400 整除的年份不是闰年
  3. 能被 400 整除的年份是闰年
javascript
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}

console.log(isLeapYear(2024)); // true
console.log(isLeapYear(2025)); // false
console.log(isLeapYear(2000)); // true
console.log(isLeapYear(1900)); // false
python
import calendar

print(calendar.isleap(2024))  # True
print(calendar.isleap(2025))  # False
print(calendar.isleap(2000))  # True
print(calendar.isleap(1900))  # False

闰年对日期计算的影响

python
from datetime import date

date1 = date(2024, 1, 1)
date2 = date(2025, 1, 1)
print(f"2024年天数: {(date2 - date1).days}")
# 2024年天数: 366

date3 = date(2025, 1, 1)
date4 = date(2026, 1, 1)
print(f"2025年天数: {(date4 - date3).days}")
# 2025年天数: 365

2月29日的特殊处理

在闰年出生在 2 月 29 日的人,平年的生日通常按 2 月 28 日或 3 月 1 日计算。大多数日期库在加减年份时会自动处理这种情况:

python
from datetime import date
from dateutil.relativedelta import relativedelta

leap_birthday = date(2024, 2, 29)
next_year = leap_birthday + relativedelta(years=1)
print(next_year)
# 2025-02-28(自动调整为2月最后一天)

two_years = leap_birthday + relativedelta(years=2)
print(two_years)
# 2026-02-28

four_years = leap_birthday + relativedelta(years=4)
print(four_years)
# 2028-02-29(再次遇到闰年)

日期格式化与解析

在日期计算之前,正确解析输入的日期字符串至关重要。不同地区有不同的日期格式习惯。

地区 格式 示例
中国 YYYY-MM-DD 2026-04-01
美国 MM/DD/YYYY 04/01/2026
欧洲 DD/MM/YYYY 01/04/2026
ISO 8601 YYYY-MM-DDTHH:mm:ssZ 2026-04-01T00:00:00Z

JavaScript 日期格式化

javascript
function formatDate(date, format) {
  const pad = n => String(n).padStart(2, '0');
  const tokens = {
    'YYYY': date.getFullYear(),
    'MM': pad(date.getMonth() + 1),
    'DD': pad(date.getDate()),
    'HH': pad(date.getHours()),
    'mm': pad(date.getMinutes()),
    'ss': pad(date.getSeconds())
  };

  return Object.entries(tokens).reduce(
    (str, [token, value]) => str.replace(token, value),
    format
  );
}

const date = new Date('2026-04-01');
console.log(formatDate(date, 'YYYY年MM月DD日'));
// "2026年04月01日"

console.log(formatDate(date, 'YYYY-MM-DD'));
// "2026-04-01"

Python 日期格式化

python
from datetime import datetime

dt = datetime(2026, 4, 1, 14, 30, 0)

print(dt.strftime('%Y年%m月%d日'))
# 2026年04月01日

print(dt.strftime('%Y-%m-%d %H:%M:%S'))
# 2026-04-01 14:30:00

print(dt.strftime('%m/%d/%Y'))
# 04/01/2026

日期字符串解析

python
from datetime import datetime

formats = [
    ('2026-04-01', '%Y-%m-%d'),
    ('04/01/2026', '%m/%d/%Y'),
    ('01/04/2026', '%d/%m/%Y'),
    ('2026年4月1日', '%Y年%m月%d日'),
]

for date_str, fmt in formats:
    parsed = datetime.strptime(date_str, fmt)
    print(f"'{date_str}' → {parsed.date()}")

常见问题

如何计算两个日期之间的天数?

用较晚的日期减去较早的日期即可。在 JavaScript 中将两个日期转换为时间戳后相减再除以 86400000(每天毫秒数)。在 Excel 中直接用两个日期单元格相减。在 Python 中,两个 date 对象相减会返回 timedelta 对象,其 .days 属性即为天数差。如果不想编写代码,也可以使用 QubitTool 日期计算器 在线即时计算。

如何在日期上加减天数?

创建日期对象后加减天数即可。JavaScript 使用 setDate(getDate() + n) 方法,Python 使用 timedelta(days=n) 进行加减,Excel 直接在日期单元格上加减数字。如果需要加减月份或年份,JavaScript 可以使用 setMonth()setFullYear(),Python 推荐使用 dateutil 库的 relativedelta,Excel 可以使用 EDATE() 函数。这些方法常用于计算截止日期、订阅到期日和合同日期。

如何计算两个日期之间的工作日?

统计两个日期之间的所有天数,排除周末(周六和周日)以及可选的公众假日。在 JavaScript 中需要遍历每一天,通过 getDay() 判断是否为周末。在 Python 中可以使用 numpy.busday_count() 高效计算。Excel 提供了 NETWORKDAYS 函数,可以直接计算工作日数,还支持通过第三个参数传入假日列表进行排除。

日历天数和工作日有什么区别?

日历天数包括所有天(工作日、周末、节假日),工作日仅计算周一至周五并排除公众假日。30 个日历天通常约包含 22 个工作日,一年通常有 250-252 个工作日。在实际应用中,合同期限、保质期等通常按日历天数计算,而项目工期、交货周期等通常按工作日计算。选择哪种计算方式取决于具体的业务场景和法律要求。

日期计算中如何处理闰年?

闰年每 4 年增加一天(2 月 29 日),但世纪年需被 400 整除才算闰年(如 2000 年是闰年,1900 年不是)。大多数编程语言和日期库会自动处理闰年,开发者无需手动干预。手动计算时,判断闰年的规则是:能被 4 整除且不能被 100 整除,或者能被 400 整除的年份为闰年。在日期加减中需要注意 2 月 29 日加 1 年后会自动调整为 2 月 28 日。

总结

日期计算是编程和日常生活中不可缺少的技能。本文涵盖了以下核心内容:

主题 要点
日期间隔计算 JavaScript 时间戳相减、Python datetime、Excel 直接相减
日期加减运算 天数、月份、年份的加减及月末自动调整
工作日计算 排除周末和假日,NETWORKDAYS 函数
时区处理 统一使用 UTC 计算,注意夏令时陷阱
闰年处理 4/100/400 规则,2月29日特殊处理
实际应用 项目管理、法律、金融、个人生活

无论使用哪种编程语言或工具,日期计算的核心原理都是一致的。建议在实际开发中使用成熟的日期库(如 Python 的 dateutil、JavaScript 的 date-fnsdayjs),避免手动处理复杂的边界情况。

如果你只是需要快速计算两个日期之间的天数、在日期上加减天数或计算工作日,无需编写代码——直接使用 QubitTool 日期计算器,输入日期即可获取结果。

👉 立即使用日期计算器