为了账号安全,请及时绑定邮箱和手机立即绑定

如何在Javascript中以mm-dd-hh格式获取两个日期的差

/ 猿问

如何在Javascript中以mm-dd-hh格式获取两个日期的差

紫衣仙女 2019-12-06 15:43:22

我可以使用moment.js或纯js获得两个日期之间的差异。


在moment.js中


var a = moment(timestamp1);

var b = moment(timestamp2);

var month =a.diff(b, 'month');

var day =a.diff(b, 'day') - month;

var year =a.diff(b, 'hours');

月返回月,日返回天差。但是我想要答案


MM-DD-hh格式例如2个月12天5小时。我无法直接转换日期,因为还有leap年等其他问题。还有什么其他办法可以全力以赴并计算一切吗?我在angular js中这样做,如果有帮助


查看完整描述

3 回答

?
萧十郎

要获得两个日期之间的精确差并不容易,因为年,月和日的长度是不同的。另外,加法不一定与减法对称,例如4月30日加1月是5月30日,但5月31日加1月30日还是7月1日吗?与2月29日前后1年相似。


以下内容尝试解决这些问题,因此,如果添加一个月超过一个月,则日期将返回到上个月的最后一天。希望这些评论足够,如果不能,请澄清。


该则DateDiff函数返回值的年,月,日,等一个数组来获取MM-DD-HH,只拿到并格式化你想要的任何方式。我提供了一个小的格式化功能,该功能仅打印出非零分量。


// Simple calculation of days between two dates based on time value

function getDaysDiff(start, end) {

  return ((parseStringUTC(end) - parseStringUTC(start))/8.64e7).toFixed(2);

}


// Expects input in ISO8601 format: yyyy-mm-ddThh:mm:ss.sssZ

// Always expects UTC

function parseStringUTC(s) {

  s = s.split(/\D/);

  s[6] = s[6]? ('0.'+ s[6]) * 1000 : 0;

  return new Date(Date.UTC(s[0],--s[1],s[2],s[3]||0,s[4]||0,s[5]||0,s[6]||0));

}


/*  Get the difference between two dates in years, months, days,

**  hours, minutes and seconds.

**

**  Difference is values to add to earlier date to reach later date.

**

**  Does not consider daylight saving changes so may be incorrect by offset

**  difference over daylight saving boundaries, so use UTC values (pass

**  values as date.toISOString() or format like ISO 8601 UTC)

**

**  @param {string} d0 - earlier date in format y-m-d h:m:s, can also be

**                       yyyy-mm-ddThh:mm:ssZ, the timezone offset is ignored

**                       the string is not validated

**  @param {string} d1 - later date in same format as above. If d1 is earlier

**                       than d0, results are unreliable.

**  @returns {Array}     values for years, months, days, hours, minutes and

**                       seconds (milliseconds as decimal part of seconds)

*/

function dateDiff(d0,d1) {

  var s = d0.split(/\D/);

  var e = d1.split(/\D/);

  // Calculate initial values for components,

  // Time component is optional, missing values treated as zero

  var ms  = (e[6]||0) - (s[6]||0);

  var sec = (e[5]||0) - (s[5]||0);

  var min = (e[4]||0) - (s[4]||0);

  var hr  = (e[3]||0) - (s[3]||0);

  var day = e[2] - s[2];

  var mon = e[1] - s[1];

  var yr  = e[0] - s[0];

  

  // Borrowing to resolve -ve values.

  if (ms < 0) {  // ms borrow from sec

    ms  += 1000;

    --sec;

  }

  if (sec < 0) { // sec borrows from min

    sec += 60;

    --min;

  }

  if (min < 0) { // min borrows from hr

    min += 60;

    --hr;

  }

  if (hr < 0) { // hr borrows from day

    hr  += 24;

    --day;

  }


  // Day borrows from month, a little complex but not too hard

  if (day < 0) {

    var prevMonLen = new Date(e[0], e[1]-1, 0).getDate();

    // If the start date is less than the number of days in the previous month,

    // set days to previous month length + current diff days value

    // Note that current diff days may have had a day borrowed, so don't use end date - start date

    // Otherwise, if the start date is equal to or greater than the number of

    // days in the previous month, just set to end date. That's because adding

    // 1 month to 30 Jan should be last day in Feb (i.e. 28 or 29), not 2 or 1 March

    // respectively, which is what happens if adding 1 month to a Date object for 30 Jan.

    // Similarly, 31 May + 1 month should be 30 June, not 1 July.

    day = s[2] < prevMonLen? prevMonLen + day : +e[2];

    --mon;

  }

  

  if (mon < 0) { // mon borrows from yr

    mon += 12;

    --yr;

  }


  // If days >= number of days in end month and end date is last day

  // of month, zero mon and add one to month

  // If then months = 12, zero and add one to years

  var endMonLen = new Date(e[0], e[1], 0).getDate();


  if (day >= endMonLen && s[2] > e[2] && e[2] == endMonLen) {

    day = 0;

    ++mon;

    if (mon == 12) {

      mon = 0;

      ++yr;

    }

  }

  return [yr,mon,day,hr,min,+(sec + '.' + ('00'+ms).slice(-3))];

}


/*  Format output from dateDiff function, e.g. 3years, 2 days, 23.12 seconds

**

**  @param {Array} v - values array in order years, months, days, hours, minutes

**                     seconds (milliseconds as decimal part of seconds)

**  @returns {string} Values with their names appended. Adds "s" to values other

**                    than 1, zero values omitted, e.g. "0 months" not returned.

*/

function formatOutput(v) {

  var values = ['year','month','day','hour','minute','second']

  return v.reduce(function (s, x, i) {

    s += x? (s.length? ' ' : '') +

         (i == 5? x.toFixed(3) : x) + ' ' + values[i] + (x==1?'':'s'):'';

    return s;

  }, '');

}


// Tests, focus on February

var dates = [

  ['2016-01-31','2016-03-01'], //  1 month   1 day  - 31 Jan + 1 month = 29 Feb

  ['2016-01-29','2016-03-01'], //  1 month   1 day  - 29 Jan + 1 month = 29 Feb

  ['2016-01-27','2016-03-01'], //  1 month   3 days - 27 Jan + 1 month = 27 Feb

  ['2016-01-27','2016-03-29'], //  2 months  2 days - 27 Jan + 2 month = 27 Mar

  ['2016-01-29','2016-03-27'], //  1 month  27 days - 29 Jan + 1 month = 29 Feb

  ['2015-12-31','2016-01-30'], // 30 days           - 31 Dec + 30 days = 30 Jan

  ['2015-12-27','2016-01-30'], //  1 month   3 days - 27 Dec + 1 month = 27 Jan

  ['2016-02-29','2017-02-28'], //  1 year could also be 11 months 30 days

                               // since 29 Feb + 11 months = 28 Feb, but 28 Feb is last day of month

                               // so roll over to full year

                               // Both work, but 1 year is more logical

  ['1957-12-04','2016-02-20'], // 58 years   2 months 16 days

  ['2000-02-29','2016-02-28'], // 15 years  11 months 30 days

                               // Not full year as Feb 2016 has 29 days

  ['2000-02-28','2016-02-28'], // 16 years

  ['2000-02-28','2016-02-29'], // 16 years  1 day

  ['2016-02-28T23:52:19.212Z','2016-12-02T01:48:57.102Z'] // 9 months 3 days 1 hour 56 minutes 37.899 seconds

];


var arr = [];

dates.forEach(function(a) {

  arr.push(a[0] + ' to ' + a[1] + '<br>' + formatOutput(dateDiff(a[0], a[1])));

});

document.write(arr.join('<br>'));

  table {

    border-collapse:collapse;

    border-left: 1px solid #bbbbbb;

    border-top: 1px solid #bbbbbb;

  }

  input {

    width: 12em;

  }

  input.bigGuy {

    width: 32em;

  }

  td {

    border-right: 1px solid #bbbbbb;

    border-bottom: 1px solid #bbbbbb;

  }

  td:nth-child(1) { text-align: right; }

<form onsubmit="this.doCalc.onclick(); return false;">

  <table>

    <tr>

      <td width="250"><label for="startDate">Start date (yyyy-mm-dd)</label>

      <td><input name="startDate" id="startDate" value="2012-08-09T22:15:03.22" size="25">

    <tr>

      <td><label for="endDate">End date (yyyy-mm-dd)</label>

      <td><input name="endDate" id="endDate" value="2013-08-13T12:10:03.22" size="25">

    <tr>

      <td><label for="dateDifference">Date difference: </label>

      <td><input name="dateDifference" readonly class="bigGuy">

    <tr>

      <td><label for="daysDifference">Days difference: </label>

      <td><input name="daysDifference" readonly>

    <tr>

      <td>

      <input type="button" value="Calc date difference" name="doCalc2" onclick="

        this.form.dateDifference.value = formatOutput(dateDiff(this.form.startDate.value, this.form.endDate.value));

        this.form.daysDifference.value = getDaysDiff(this.form.startDate.value, this.form.endDate.value) + ' days';

      ">

      <td><input type="reset">

  </table>

</form>

注意事项:

  1. 5月31日至6月30日为1个月。7月1日是没有意义的。

  2. 在a年中,1月31日至2月29日为1个月,至2016年2月28日为28天。

  3. 1月31日至2月28日不是a年,则为1个月。

  4. 2016年2月29日至2017年2月28日为1年,因为2月28日是该月的最后一天

  5. 2016年2月29日至2020年2月28日为3年11个月30天,因为2月28日不是2020年每月的最后一天。

  6. 无需使用Date对象就可以完全实现此解决方案,我只是为了方便获取一个月中的日期而使用它,但是不使用Date的替代方法大约需要4行代码。


查看完整回答
反对 回复 2019-12-06
?
ITMISS

var date1 = new Date("4/14/2016");

 var date2 = new Date("10/16/2016");

 var timeDiff = Math.abs(date2.getTime() - date1.getTime());


 var newDate = new Date(timeDiff);

 alert(newDate);

 alert("Month " + (newDate.getUTCMonth() + 1));

 alert("Date " + newDate.getUTCDate());

 alert("Hour " + newDate.getUTCHours());


查看完整回答
反对 回复 2019-12-06
?
红颜莎娜

您无法将差异(差异结果是数字)转换为MM-DD-hh格式,因为某些月份的长度为30天,而另一些月份的长度为31天。


可以从开始和结束日期时间计算得出。


您正在寻找类似的功能,但不完全相同


moment("2010-01-01").from("2010-12-01")

结果:一年前


moment("2010-01-01").from("2010-12-01", true)

结果:一年


查看完整回答
反对 回复 2019-12-06

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信