【问题标题】:Javascript: convert number of days to years, months and daysJavascript:将天数转换为年、月和日
【发布时间】:2020-02-08 18:42:07
【问题描述】:

我有几天、几个月和几年。我在他们之间做计算。这意味着我必须将 2 年 3 个月零 10 天除以 1/4。现在我有以下代码:

const getCurrentDate = moment().format("YYYY-MM-DD");
const timeEnd = moment(moment(DefEndDate).format("YYYY-MM-DD"));
const diff = timeEnd.diff(getCurrentDate);
const diffDuration = moment.duration(diff);
const diffCount = moment.duration(diff).asDays();
console.log(diffCount);
console.log("Years:", diffDuration.years());
console.log("Month:", diffDuration.months());
console.log("Days:", diffDuration.days());

const diffCount = moment.duration(diff).asDays(); //Get it as days
const [unserve, setUnserve] = useState(''); //set value to variable
    const res = unserve.split('/'); //split 1/4 to 1.4
    const x = parseFloat(res[0] + "." + res[1]); //convert it to float
    var quotient = Math.floor(diffCount/x); //calculate
    console.log(quotient);
    //returned 832 / 1.4 = 594 days

现在我需要将输出数字(天)返回到年、月和日。我不能那样做。我该如何转换?还有一个问题是,这种方式能成为最优解吗?

【问题讨论】:

  • @GennadyDogaev 谢谢,但我需要在没有额外库的情况下这样做。
  • @OktamYaqubov 好吧,你已经在使用 momentjs...
  • 2 years 3 months --- 哪一年哪几个月?一年或一个月的天数不是恒定的
  • 一个月可以是 28、29、30 或 31 天。一年可以是 365 或 366。那么你将如何处理呢? 2018年12月30日到2019年3月1日你想要什么结果,2019年12月30日到2020年3月1日你想要什么结果?

标签: javascript date momentjs


【解决方案1】:

我无法决定您真正想要做的是将日期范围划分为具有相同天数的固定数量的期间,还是从日期开始,添加以年、月和日为单位的期间以获得结束日期,然后将其分成相等的时间段。

以下假设是后者。

我必须将 2 年 3 个月 10 天除以 1/4

该期间所涵盖的天数取决于它的往返日期,因此您必须从该范围的开始日期和结束日期开始。

在您的代码中:

const getCurrentDate = moment().format("YYYY-MM-DD");

getCurrentDate 设置为类似 2020-02-11 的字符串。

const timeEnd = moment(moment(DefEndDate).format("YYYY-MM-DD"));

getCurrentDate 的字符串值创建一个时刻对象,并将 timeEnd 设置为另一个字符串。

const diff = timeEnd.diff(getCurrentDate);

这试图调用timeEnddiff方法,它是一个字符串。字符串没有 diff 方法,因此表达式返回未定义,尝试调用它会引发类似 TypeError: '2020-02-11'.diff is not a function 的错误。

您的其余代码似乎基于算法

如果您有一个以年、月、日等为单位的预定时间段。您可以从开始日期开始,添加时间段,然后获取天数差异。将该差除以您想要的期间数,然后按顺序相加以获得不同的结束日期。

以下示例使用 moment.js,因为您似乎正在使用它,但是没有库的版本也有同样的困难。它返回一个日期数组,从开始日期开始,因此日期比句点多一个。

function getDates(
  start = new Date(),
  years = 0,
  months = 0,
  days = 0,
  parts = 1) {
  
  // Get start and end as moment objects
  let m = moment(start).startOf('day');
  let end = moment(m);
  end.add({years:years, months:months, days:days});
  
  // Get days difference and number of days to add for each period
  let daysDiff = end.diff(m, 'days');
  let f = daysDiff / parts;  
  let dayArray = [m.format('YYYY-MM-DD')];
  let i = 0;

  while ((f * ++i) <= daysDiff) {
    let d = moment(m).add(f * i, 'days')
    dayArray.push(d.format('YYYY-MM-DD'));
  }
  
  return dayArray;      
}

// Get dates for 4 even periods over 2 years, 3 months and
// 10 days from today
console.log(getDates(new Date(), 2, 3, 10, 4));
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"&gt;&lt;/script&gt;

由于子周期长度几乎总是不是偶数天(在上述情况下约为 207.5),因此我允许格式化以有效截断一天的小数部分。您可能希望使用其他一些更均匀分布余数的舍入算法。

另一方面,如果您有开始日期和结束日期并且想要相同数量的句点,则以下内容要简单得多(并且不使用库):

// Helpers - use UTC do avoid DST issues
function toUTCDate(s) {
  let b = s.split(/\D/);
  return new Date(Date.UTC(b[0], --b[1], b[2]));
}

function formatUTC(date) {
  return date.toISOString().substr(0, 10);
}

/* @param {string} start - date string in format 'YYYY-MM-DD'
** @param {string} end   - date string in format 'YYYY-MM-DD'
** @param (numbe} n - number of required periods
** @returns {Array} array of date strings in format 'YYYY-MM-DD'
*/
function periods(start, end, n) {
  let s = toUTCDate(start);
  let e = toUTCDate(end);
  let diff = e - s;
  let f = diff / n;
  let result = [formatUTC(s)];

  // Allow for rounding of decimal f in comparison
  while (e - s > n) {
    s.setTime(s.getTime() + f);
    result.push(formatUTC(s))
  }

  return result;
}

console.log(periods('2020-02-09','2022-05-19', 4));

这两种方法产生的结果略有不同,你需要弄清楚这是否重要。

【讨论】:

    【解决方案2】:

    很久以前我用这样的代码将秒转换为小时、分钟和秒:

    var hours = Math.floor(sec / 3600);
    var minutes = Math.floor((sec - hours * 3600) / 60);
    var seconds = Math.round(sec - hours * 3600 - minutes * 60);
    

    天、月、年的数学应该有点相似,但我生锈的大脑不想去想它

    UPD

    这个功能似乎可以满足你的需要

    const daysFmt = days => {
      const years = Math.floor(days / 365);
      const months = Math.floor((days - years * 365) / 30);
      const d = Math.round(days - years * 365 - months * 30);
    
      let res = [];
      if (years > 0) {
        res.push(years + ' y');
      }
      if (months > 0) {
        res.push(months + ' m');
      }
      if (d > 0) {
        res.push(d + ' d');
      }
    
      return res.join(', ');
    }
    

    但是这个解决方案有一个细微差别:它假设月份 = 30 天。如果输入为 31,您可能需要添加 if 语句以返回“1 m”,或者如果输入小于 32,则仅返回天数。测试结果:

    daysFmt(31);
    "1 m, 1 d"
    daysFmt(180);
    "6 m"
    daysFmt(185);
    "6 m, 5 d"
    daysFmt(356);
    "11 m, 26 d"
    daysFmt(365);
    "1 y"
    daysFmt(420);
    "1 y, 1 m, 25 d"
    daysFmt(3650);
    "10 y"
    daysFmt(3685);
    "10 y, 1 m, 5 d"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多