You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中实现两个波斯历日期相减计算时长的问题求助

解决波斯历日期与API日期相减的问题

我明白你遇到的困扰了——想拿当前波斯历日期和API返回的日期计算时间差,但因为把波斯历转成字符串后没法生成有效的时间戳,导致减法运算直接失败。咱们先拆解问题根源,再一步步搞定:

问题出在哪?

你原来的代码里,new Date().toLocaleDateString('fa-IR').replace(...)得到的是波斯历日期的字符串(比如"1403/05/12"),哪怕替换成阿拉伯数字后还是字符串类型。调用valueOf()对字符串来说,返回的只是字符串本身,不是时间戳;而new Date(arr).valueOf()是把API返回的日期转成了数字类型的时间戳,字符串减数字自然会得到NaN或者错误结果。

要解决这个问题,核心是把波斯历日期转换成JavaScript能识别的公历Date对象,这样才能拿到正确的时间戳进行计算。下面给你两种可行方案:


方案一:用原生Intl API处理(无需第三方库)

原生的Intl.DateTimeFormat可以帮我们解析波斯历的日期部分,再转成公历Date对象。注意要指定正确的时区(伊朗标准时间Asia/Tehran),避免日期偏移:

let arr;
this.formsService.get_date_duration().subscribe(res => {
  arr = res;
  
  // 1. 获取当前波斯历的年、月、日(阿拉伯数字)
  const persianFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    timeZone: 'Asia/Tehran'
  });
  const dateParts = persianFormatter.formatToParts(new Date());
  const persianYear = parseInt(dateParts.find(p => p.type === 'year').value);
  const persianMonth = parseInt(dateParts.find(p => p.type === 'month').value) - 1; // 月份从0开始计数
  const persianDay = parseInt(dateParts.find(p => p.type === 'day').value);
  
  // 2. 将波斯历日期转换为公历Date对象(用反向格式化技巧)
  const gregorianFormatter = new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    timeZone: 'Asia/Tehran'
  });
  const tempDate = new Date(Date.UTC(persianYear, persianMonth, persianDay));
  const gregorianDateStr = gregorianFormatter.format(tempDate);
  const eventStartTime = new Date(gregorianDateStr).setHours(0, 0, 0, 0); // 设置为当天0点的时间戳
  
  // 3. 处理API返回的日期,转成时间戳
  const eventEndTime = new Date(arr).setHours(0, 0, 0, 0);
  
  // 4. 计算时长(单位:毫秒),按需转成天数/小时等
  const duration = eventStartTime - eventEndTime;
  const daysDiff = Math.abs(duration) / (1000 * 60 * 60 * 24);
  
  console.log("时长(毫秒):", duration);
  console.log("天数差:", daysDiff.toFixed(1));
});

方案二:用专门的波斯历库(更可靠)

原生API处理波斯历多少有点绕,想省心的话可以用jalaali-js这个轻量级库,它专门用来处理波斯历(Jalaali)和公历的转换:

第一步:安装库

npm install jalaali-js

第二步:在代码中使用

import * as jalaali from 'jalaali-js';

let arr;
this.formsService.get_date_duration().subscribe(res => {
  arr = res;
  
  // 1. 获取当前时间对应的波斯历日期
  const now = new Date();
  const currentPersian = jalaali.toJalaali(now.getFullYear(), now.getMonth() + 1, now.getDate());
  // currentPersian 结构:{ jy: 1403, jm: 5, jd: 12 }
  
  // 2. 把波斯历日期转成公历日期
  const currentGregorian = jalaali.toGregorian(currentPersian.jy, currentPersian.jm, currentPersian.jd);
  // currentGregorian 结构:{ gy: 2024, gm: 8, gd: 3 }
  
  // 3. 生成当天0点的时间戳
  const eventStartTime = new Date(currentGregorian.gy, currentGregorian.gm - 1, currentGregorian.gd).setHours(0, 0, 0, 0);
  
  // 4. 处理API返回的日期(如果API返回波斯历字符串,也可以用jalaali解析)
  const eventEndTime = new Date(arr).setHours(0, 0, 0, 0);
  
  // 5. 计算时长
  const duration = eventStartTime - eventEndTime;
  console.log("时长(毫秒):", duration);
  console.log("天数差:", Math.round(Math.abs(duration) / (1000 * 60 * 60 * 24)));
});

如果API返回的本身就是波斯历字符串(比如"1403/05/10"),可以直接解析后转公历:

// 解析API返回的波斯历日期
const [jy, jm, jd] = arr.split('/').map(Number);
const endGregorian = jalaali.toGregorian(jy, jm, jd);
const eventEndTime = new Date(endGregorian.gy, endGregorian.gm - 1, endGregorian.gd).setHours(0, 0, 0, 0);

内容的提问来源于stack exchange,提问作者hanie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 09:27:41