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

要获得两个日期之间的精确差并不容易,因为年,月和日的长度是不同的。另外,加法不一定与减法对称,例如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] + '
' + formatOutput(dateDiff(a[0], a[1])));

});

document.write(arr.join('
'));

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; }

Start date (yyyy-mm-dd)
End date (yyyy-mm-dd)
Date difference:
Days difference:

注意事项:5月31日至6月30日为1个月。7月1日是没有意义的。

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

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值