如何获得在Javascript MM-DD-HH格式两个日期的差别 [英] How to get the difference of two dates in mm-dd-hh format in Javascript

查看:256
本文介绍了如何获得在Javascript MM-DD-HH格式两个日期的差别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

在moment.js

  VAR一个=时刻(timestamp1与);
变种B =时刻(与timestamp2);
VAR月= a.diff(B,'月');
VAR天= a​​.diff(B,'天') - 个月;
VAR年= a.diff(B,'小时');

一个月回报月,天天回差。但我想在回答

有关实例2个月12日14小时MM-DD-HH格式。我不能转换当日直接导致有像闰年等问题。是否有任何其他方式然后全力以赴,计算一切?我在角JS这样做,如果这是任何帮助。


解决方案

获取两个日期之间的precise差别并不简单,因为年,月和日有不同的长度。此外,加入不一定与减法对称,例如是4月30日加上一个月是5月30日,但5月31日加上一个月6月30日或7月1日?类似与2月29日加或减1年。

以下尝试来处理这些问题,因此,如果添加超过一个额外月一个月辊,日期返回到previous月的最后一天。希望评论是足够的,如果不是,要求澄清。

则DateDiff 的函数返回值的年,月,日等阵列来获得MM-DD-HH,只得到并格式化你想要的任何方式。我已经包含了小格式化功能,只是打印出非零分量。

\r
\r
基于时间值的两个日期之间的天

//简单计算\r
功能getDaysDiff(起点,终点){\r
  收益率((parseStringUTC(完) - parseStringUTC(开始))/ 8.64e7).toFixed(2);\r
}\r
\r
//预计ISO8601格式输入:YYYY-MM-DDTHH:MM:ss.sssZ\r
//总是期望UTC\r
功能parseStringUTC(多个){\r
  S = s.split(/ \\ D /);\r
  S [6] = S [6]? ('0'+ S [6])* 1000:0;\r
  返回新日期(Date.UTC(S [0], - S [1],S [2],S [3] || 0,S [4] || 0,S [5] || 0,S [6] || 0));\r
}\r
\r
/ *获取年两个日期之间的差异,月,日,\r
**小时,分钟和秒。\r
**\r
**不同的是值添加到提前到达以后的日期。\r
**\r
**不考虑夏令时的变化,可能会抵消不正确\r
**在夏令界限区别,所以使用UTC值(通\r
**值date.toISOString()或类似ISO 8601 UTC格式)\r
**\r
** @param {string}里D0 - 格式Y-M-深高更早的日期:M:S,也可\r
** YYYY-MM-DDTHH:MM:SSZ,时区将被忽略偏移\r
**字符串不验证\r
** @param {}串D1 - 在与上述相同的格式稍后的日期。如果D1早\r
**比D0,结果是不可靠的。\r
**年,月,日,时,分@Returns {}数组和值\r
**秒(毫秒为秒小数部分)\r
* /\r
函数DATEDIFF(D0,D1){\r
  变种S = d0.split(/ \\ D /);\r
  变种E = d1.split(/ \\ D /);\r
  //为组件计算的初始值,\r
  //时间组件是可选的,缺失值当作零\r
  变种毫秒=(E [6] || 0) - (S [6] || 0);\r
  变种秒=(E [5] || 0) - (S [5] || 0);\r
  变种分钟=(E [4] || 0) - (S [4] || 0);\r
  无功小时=(E [3] || 0) - (S [3] || 0);\r
  VAR天= E [2] - S [2];\r
  VAR周一= E [1] - S [1];\r
  VAR年= E [0] - S [0];\r
  \r
  //借款来解决-ve的值。\r
  如果(毫秒℃,){//毫秒从秒借\r
    MS + = 1000;\r
    --sec;\r
  }\r
  如果(秒-1; 0){//秒从分借用\r
    秒+ = 60;\r
    --min;\r
  }\r
  如果(分钟< 0){//分钟从小时借用\r
    分+ = 60;\r
    --hr;\r
  }\r
  如果(hr的0){//小时从天借用\r
    HR + = 24;\r
     - 天;\r
  }\r
\r
  //日从一个月,一个有点复杂,但借用不能太硬\r
  如果(天℃,){\r
    VAR prevMonLen =新的日期(E [0],E [1] -1,0).getDate();\r
    //如果起始日期小于几天在previous月份的数字,\r
    //集天previous月长+电流差异值天\r
    //注意当前的diff天可能有一天借来的,所以不要使用结束日期 - 开始日期\r
    //否则,如果开始日期比的数目等于或大于\r
    在previous月//日,刚刚成立到结束日期。这是因为加入\r
    // 1个月至1月30日应该是最后一天2月(即28或29),而不是2或3月1日\r
    //分别,这是如果为1每月新增一个Date对象为1月30日会发生什么\r
    //同样,5月31日+ 1个月应该是6月30日,而不是7月1日。\r
    天= S [2]所述; prevMonLen? prevMonLen +天:+ E [2];\r
    --mon;\r
  }\r
  \r
  如果(星期一及小于0){//从星期一借用年\r
    周一+ = 12;\r
    --yr;\r
  }\r
\r
  //如果天> =在月末和结束日期的天数是最后一天\r
  一个月零孟//并加1以一个月\r
  //如果那么个月= 12,零加一年前\r
  VAR endMonLen =新的日期(E [0],E [1],0).getDate();\r
\r
  如果(日> = endMonLen和放大器;&安培; S [2]> E [2]和放大器;急症[2] == endMonLen){\r
    天= 0;\r
    周一++;\r
    如果(星期一== 12){\r
      周一= 0;\r
      ++年;\r
    }\r
  }\r
  返回[岁,星期一,日,小时,分钟,+('。'秒+ +(00 + MS).slice(-3))];\r
}\r
\r
/ *格式从DateDiff函数,例如输出3年,2天,23.12秒\r
**\r
** @param {阵}伏 - 值阵列,以年,月,日,小时,分钟\r
**秒(毫秒为秒小数部分)\r
** @Returns {string}里用追加他们的名字值。添加的s到其他值\r
**不是1,零值省略,例如0个月不予退换。\r
* /\r
功能formatOutput(ⅴ){\r
  VAR值= ['年','月','天','小时','分钟','第二次']\r
  返回v.reduce(功能(S,X,I){\r
    S + = X? (s.length'?':'')+\r
         (ⅰ== 5 x.toFixed(3):X')+''+值[I] +(X == 1?:s的):'';\r
    返回S;\r
  },'');\r
}\r
\r
//测试,专注于二月\r
VAR日期= [\r
  [2016年1月31日,2016年3月1日'],// 1个月1天 - 1月31日+ 1个月= 2月29日\r
  [2016年1月29日,2016年3月1日'],// 1个月1天 - 1月29日+ 1个月= 2月29日\r
  [2016年1月27日,2016年3月1日'],// 1个月3天 - 1月27日+ 1个月= 2月27日\r
  [2016年1月27日,2016年3月29日'],// 2月2天 - 1月27日+ 2月= 3月27日\r
  [2016年1月29日,2016年3月27日'],//1个月27天 - 1月29日+ 1个月= 2月29日\r
  [2015年12月31日,2016年1月30日'],//30天 - 12月31日+ 30天= 30一月\r
  [2015年12月27日,2016年1月30日'],// 1个月3天 - 12月27日+ 1个月= 1月27日\r
  [2016年2月29日,2017年2月28日'],// 1年可能也11个月30天\r
                               //自2月29日+ 11个月= 2月28日,但2月28日是本月的最后一天\r
                               //所以翻转到全年\r
                               //两个工作,但1年的多个逻辑\r
  [1957年12月4日,2016年2月20日'],//58年2个月16天\r
  ['2000-02-29','2016年2月28日'],// 15年11月个月的30天\r
                               //没有满一年,2016年2月有29天\r
  ['2000年2月28日,2016年2月28日'],//16年\r
  [2000年2月28日,2016年2月29日'],//16年1天\r
  ['2016-02-28T23:52:19.212Z','2016-12-02T01:48:57.102Z'] //9个月3天1小时56分钟37.899秒\r
];\r
\r
VAR ARR = [];\r
dates.forEach(函数(){\r
  arr.push(一个[0] +至+一[1] +'&所述峰; br>'+ formatOutput(DATEDIFF(一个[0],A [1])));\r
});\r
的document.write(arr.join('< BR>'));

\r

表{\r
    边境崩溃:崩溃;\r
    左边框:1px的固体#bbbbbb;\r
    边境顶:1px的固体#bbbbbb;\r
  }\r
  输入{\r
    宽度:12em;\r
  }\r
  input.bigGuy {\r
    宽度:32em;\r
  }\r
  TD {\r
    右边框:1px的固体#bbbbbb;\r
    下边框:1px的固体#bbbbbb;\r
  }\r
  TD:第n个孩子(1){文本对齐:权利; }

\r

<形成的onsubmit =this.doCalc.onclick();返回false; >\r
  <表>\r
    &所述; TR>\r
      < TD WIDTH =250><标签=的startDate>开始日期(YYYY-MM-DD)LT; /标签>\r
      < TD><输入名称=的startDateID =的startDateVALUE =2012-08-09T22:15:03.22大小=25>\r
    &所述; TR>\r
      < TD><标签=结束日期>结束日期(YYYY-MM-DD)LT; /标签>\r
      < TD><输入名称=结束日期ID =结束日期值=2013-08-13T12:10:03.22大小=25>\r
    &所述; TR>\r
      < TD><标签=dateDifference>的时间差:LT; /标签>\r
      < TD><输入名称=dateDifference只读类=bigGuy>\r
    &所述; TR>\r
      < TD><标签=daysDifference>天差异:其中; /标签>\r
      < TD><输入名称=daysDifference只读>\r
    &所述; TR>\r
      &所述; TD>\r
      <输入类型=按钮值=计算时间差NAME =doCalc2的onclick =\r
        this.form.dateDifference.value = formatOutput(DATEDIFF(this.form.startDate.value,this.form.endDate.value));\r
        this.form.daysDifference.value = getDaysDiff(this.form.startDate.value,this.form.endDate.value)+'天';\r
      >\r
      < TD><输入类型=复位>\r
  < /表>\r
< /形式为GT;

\r

\r
\r

需要注意以下几点:


  1. 5月31日至30日六月正是1个月。它没有意义为它是7月1日。

  2. 在一个闰年,1月31日至2月29日为1个月,至2016年2月28日是28天。

  3. 不要在闰年,1月31日至2月28日为1个月。

  4. 2016年2月29日至2017年2月28日为1年,自2月28日是本月
  5. 的最后一天
  6. 2016年2月29日至2月28日2020年3年11个月30天,因为2月28日是不是一个月的2020年的最后一天。

  7. 这个解决方案可以完全实现,而不使用Date对象,我只是用它方便获得天一个月,但不使用日期的选择是约4 code线。

I can get the difference between two dates using moment.js or plain js.

in 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');

month returns month , days return difference in days . But I want the answer in

MM-DD-hh format for example 2 months 12 days 5 hours . I can not convert the day directly cause there is other issues like leap year . Is there any other way then going all out and calculating everything ? I am doing this in angular js if that is of any help

解决方案

Getting the precise difference between two dates is not simple as years, months, and days have different lengths. Also, adding is not necessarily symmetric with subtraction, e.g. is 30 April plus one month is 30 May, but is 31 May plus one month 30 June or 1 July? Similar with 29 Feb plus or minus 1 year.

The following tries to deal with those issues, so that if adding a month rolls over an extra month, the date is returned to the last day of the previous month. Hopefully the comments are sufficient, if not, ask for clarification.

The dateDiff function returns an array of the values for years, months, days, etc. To get MM-DD-hh, just get that and format it any way you want. I've included a small formatting function that just prints out the non–zero components.

// 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>

Some things to note:

  1. 31 May to 30 June is 1 month. It doesn't make sense for it to be 1 July.
  2. In a leap year, 31 Jan to 29 Feb is 1 month, to 28 Feb 2016 is 28 days.
  3. Not in a leap year, 31 Jan to 28 Feb is 1 month.
  4. 29 Feb 2016 to 28 Feb 2017 is 1 year, since 28 Feb is the last day of the month
  5. 29 Feb 2016 to 28 Feb 2020 is 3 years, 11 months and 30 days since 28 Feb is not the last day of the month in 2020.
  6. This solution can be implemented entirely without using Date objects, I've just used it for convenience for getting the days in a month, but an alternative that doesn't use a Date is about 4 lines of code.

这篇关于如何获得在Javascript MM-DD-HH格式两个日期的差别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆