我想以这种格式准确地显示用户的年龄。似乎闰年使输出有点出乎意料(我23岁,而我的输出是22.9)。有什么我可以做的不同来解释这个吗?
var t= (new Date()) - (new Date(1993,3,1));
t/= (1000*60*60*24*365);
http://codepen.io/kylebillings/pen/RaVLBM
提前感谢您解决问题的帮助!
答案 0 :(得分:0)
在两个日期之间表达时间的问题是,有很多关于如何处理不同长度的年,月和日的决定,例如
如果有人在2月29日出生,他们会在2月28日或次年3月1日结束吗?主管部门(和人民)的意见不同。
5月31日加6月30日或7月1日?
夏令时结束时,一段时间会发生两次。对于那个时期的时间,是否应该使用更早或更晚的时间?
确定两个日期之间的年,月,日等的特定算法是否正确取决于您对上述内容的回答。如果您选择使用库,您应该知道它如何处理上述所有内容并确保它适合使用它的人。
下面是一个计算两个日期之间差异的函数,基本算法是计算出必须添加到较早日期的值才能到达更晚的日期。将截至3月31日的一个月添加到6月30日,因此没有月份滚动。同样,2月29日加一年是2月28日,而不是3月1日。夏令时可能会有一些怪癖,它依赖浏览器来做到这一点(最好是变化,在某些情况下是完全错误的),所以避免DST转换期。我有一个算法可以修复那些发布的算法,但我还没有为它开发代码。
因此,以下内容可能适用与否,但它以一致的方式处理问题,并显示比我遇到的其他算法更准确的通用算法。它使用自己的ISO 8601扩展格式日期解析器来删除前面的浏览器错误,但它无法全部删除它们。 Safari在夏令时转换方面存在问题。这只是完成工作的一种方式,不一定是明确的。有一套广泛的测试,我想我已经涵盖了所有测试,但只有进一步的测试才会证实这一点。
代码在每个浏览器中运行回IE 5,但运行测试需要 .every , .forEach 和 .toISOString
// Ensure consistent parsing of ISO 8601 date strings. Some browsers will still parse
// ISO dates without a timezone as UTC (looking at you, Safari). Also, some may parse
// ISO dates without a timezone as local but most us UTC (inconsistent with ISO 8601)
// Certain versions of Chrome, allow out of bounds values in ISO 8601 strings.
// IE 8 and lower will not parse ISO 8601 strings at all.
//
// Date (and time) only treated as local: 2016-02-29, 2016-02-29T12:23:57
//
// Date with timezone applies the offset: 2016-02-29Z, 2016-02-29+10:00, 2016-02-29T12:23:57+10:00
function parseISO (s) {
// Get offset if s ends in Z/z or +/-dd:dd
var zone = /z$/i.test(s)? ['+00:00'] : s.match(/[+-]\d\d:\d\d$/);
// Trim offset from string before getting other parts
// Otherwise valid strings like 2016T-04:30 will break (2016 with offset -04:30)
var b = (zone? s.replace(/z$|[+-]\d\d:\d\d$/i,'') : s).split(/\D/);
// Resolve zone to ISO 8601 sign orientation and minutes, or set to null if missing
if (zone) {
var sign = /^-/.test(zone[0])? -1 : 1;
var z = zone[0].match(/\d+/g);
zone = sign * (z[0]*60 + Number(z[1]));
}
// Create date. If zone available, use UTC and zone, otherwise use local and hope
// that the Date constructor gets it right for DST
if (zone !== null) {
// y m d h m s ms
return new Date(Date.UTC(b[0], (b[1]? b[1]-1 : 0), b[2]||1, b[3]||0, (b[4]||0) - zone, b[5]||0, ((b[6]||'0')+'00').slice(0,3)));
} else {
return new Date( b[0], (b[1]? b[1]-1 : 0), b[2]||1, b[3]||0, b[4]||0, b[5]||0, ((b[6]||'0')+'00').slice(0,3));
}
}
// If precise is true, then time is used, otherwise only the
// date difference is returned
function dateDiff(startDate, endDate, precise) {
// If start is after end, swap dates
if (startDate > endDate) {
var t = startDate;
startDate = endDate;
endDate = t;
}
var years = months = days = hrs = mins = secs = ms = 0;
var d0 = new Date(+startDate), d1 = new Date(+endDate);
var dx;
// Add years to a date. Only tricky one is Feb 29.
function addYears(date, years) {
var startMonth = date.getMonth();
date.setFullYear(date.getFullYear() + years);
// Catch Feb 29 -> March 1
if (date.getMonth() != startMonth) {
date.setDate(0);
}
return date;
}
// Add months to a date. If goes beyond end of month when it shouldn't, trim
// to last day of epxected month (e.g. 31 May + 1 => 31 June => 1 July => 30 June)
function addMonths(date, months){
var t = new Date(+date);
var startDate = date.getDate();
date.setMonth(date.getMonth() + +months);
// If gone past end of month, set to last day of previous month
if (date.getDate() != startDate) {
date.setDate(0);
}
return date;
}
// Return number of days in month for date
function daysInMonth(date) {
var d = new Date(+date);
d.setMonth(d.getMonth() + 1, 0);
return d.getDate();
}
// If precision not required, set hours to start of day
if (!precise) {
d0.setHours(0,0,0,0);
d1.setHours(0,0,0,0);
}
// Temp date for doing initial estimate
dx = new Date(+d0);
// Get year difference, add to early date (use temp date)
years = d1.getFullYear() - d0.getFullYear();
addYears(dx, years);
// If gone past end, subtract 1 and update real early date
if (dx > d1) years -= 1;
addYears(d0, years);
// Reset temp date
dx = new Date(+d0);
// Do months as for years
months = ((d1.getMonth() + 12) - d0.getMonth()) % 12;
// If month difference is zero but days are more than 360, must be next year so make months 11
months = (d1 - d0) / 8.64e7 > 330? 11 : months;
addMonths(dx, months);
if (dx > d1) months -= 1;
addMonths(d0, months);
dx = new Date(+d0);
// From here everything is predictable (even daylight saving, as long as the UA gets it right)
var diff = d1 - d0;
days = diff / 8.64e7 | 0;
hrs = (diff % 8.64e7) / 3.6e6 | 0;
mins = (diff % 3.6e6) / 6e4 | 0;
secs = (diff % 6e4) / 1e3 | 0;
ms = diff % 1e3;
return {y:years, m:months, d:days, hr:hrs, min:mins, sec:secs, ms:ms};
}
// Run date tests
function sameAs(a0, a1) {
return a0.every(function (v, i){return a1[i] == v});
}
var resultHTML = ['<table><tr><th>#<th>Start<th>End<th>Precise<th>Expect<th>Got'];
[
//*
{start:'2016-01-31T00:00:00', end:'2016-01-31T00:00:00', precise: true, expect: [0,0,0,0,0,0,0]},
{start:'2016-01-31T00:00:00', end:'2016-01-31T00:00:00', precise: false, expect: [0,0,0,0,0,0,0]},
{start:'2016-01-31T00:00:00', end:'2017-03-01T00:00:00', precise: true, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-31T00:00:00', end:'2017-03-01T00:00:00', precise: false, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-29T00:00:00', end:'2017-03-01T00:00:00', precise: true, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-29T00:00:00', end:'2017-03-01T00:00:00', precise: false, expect: [1,1,1,0,0,0,0]},
{start:'2016-02-29T00:00:00', end:'2017-02-28T00:00:00', precise: true, expect: [1,0,0,0,0,0,0]},
{start:'2016-02-29T00:00:00', end:'2017-02-28T00:00:00', precise: false, expect: [1,0,0,0,0,0,0]},
//*/
{start:'2016-02-29T00:00:01.1Z', end:'2017-02-28T00:00:00Z', precise: true, expect: [0,11,29,23,59,58,900]},
{start:'2016-02-29T00:00:01.1Z', end:'2017-02-28T00:00:00Z', precise: false, expect: [1,0,0,0,0,0,0]}, //*,
{start:'2016-02-28T00:00:01.1', end:'2017-02-28T00:00:00', precise: true, expect: [0,11,30,23,59,58,900]},
{start:'2016-02-28T00:00:01.1', end:'2017-02-28T00:00:00', precise: false, expect: [1,0,0,0,0,0,0]},
{start:'2016-02-27T00:00:01.1', end:'2017-02-28T00:00:00', precise: true, expect: [1,0,0,23,59,58,900]},
{start:'2016-02-27T00:00:01.1', end:'2017-02-28T00:00:00', precise: false, expect: [1,0,1,0,0,0,0]},
{start:'2016-01-30T00:00:00', end:'2017-03-01T00:00:00', precise: true, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-30T00:00:00', end:'2017-03-01T00:00:00', precise: false, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-30T00:00:01.001', end:'2017-03-01T00:00:00', precise: true, expect: [1,1,0,23,59,58,999]},
{start:'2016-01-30T00:00:01.001', end:'2017-03-01T00:00:00', precise: false, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-31T00:00:01.001', end:'2017-03-01T00:00:00', precise: true, expect: [1,1,0,23,59,58,999]},
{start:'2016-01-31T00:00:01.001', end:'2017-03-01T00:00:00', precise: false, expect: [1,1,1,0,0,0,0]},
{start:'2016-01-30T00:00:01.001', end:'2017-03-02T00:00:00', precise: true, expect: [1,1,1,23,59,58,999]},
{start:'2016-01-30T00:00:01.001', end:'2017-03-02T00:00:00', precise: false, expect: [1,1,2,0,0,0,0]},
{start:'2016-10-30T00:00:00', end:'2016-12-31T00:00:00', precise: true, expect: [0,2,1,0,0,0,0]},
{start:'2016-10-30T00:00:00', end:'2016-12-31T00:00:00', precise: false, expect: [0,2,1,0,0,0,0]},
{start:'2016-10-30T00:00:00.1', end:'2016-12-31T00:00:00', precise: true, expect: [0,2,0,23,59,59,900]},
{start:'2016-10-30T00:00:00.1', end:'2016-12-31T00:00:00', precise: false, expect: [0,2,1,0,0,0,0]},
{start:'2016-10-31T00:00:00', end:'2016-12-30T00:00:00', precise: true, expect: [0,1,30,0,0,0,0]},
{start:'2016-10-31T00:00:00', end:'2016-12-30T00:00:00', precise: false, expect: [0,1,30,0,0,0,0]},
{start:'2016-01-31T00:00:00Z', end:'2016-01-31T00:00:00Z', precise: true, expect: [0,0,0,0,0,0,0]}, // 0
{start:'2016-01-31T00:00:00Z', end:'2016-01-31T00:00:00Z', precise: false, expect: [0,0,0,0,0,0,0]}, // 1
{start:'2016-01-31T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: true, expect: [1,1,1,0,0,0,0]}, // 2
{start:'2016-01-31T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: false, expect: [1,1,1,0,0,0,0]}, // 3
{start:'2016-01-29T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: true, expect: [1,1,1,0,0,0,0]}, // 4
{start:'2016-01-29T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: false, expect: [1,1,1,0,0,0,0]}, // 5
{start:'2016-01-30T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: true, expect: [1,1,1,0,0,0,0]}, // 6
{start:'2016-01-30T00:00:00Z', end:'2017-03-01T00:00:00Z', precise: false, expect: [1,1,1,0,0,0,0]}, // 7
{start:'2016-01-30T00:00:01Z', end:'2017-03-01T00:00:00Z', precise: true, expect: [1,1,0,23,59,59,0]}, // 8
{start:'2016-01-30T00:00:01Z', end:'2017-03-01T00:00:00Z', precise: false, expect: [1,1,1,0,0,0,0]}, // 9
{start:'2016-10-30T00:00:00Z', end:'2016-12-31T00:00:00Z', precise: true, expect: [0,2,1,0,0,0,0]}, // 10
{start:'2016-10-30T00:00:00Z', end:'2016-12-31T00:00:00Z', precise: false, expect: [0,2,1,0,0,0,0]}, // 11
{start:'2016-10-31T00:00:00Z', end:'2016-12-30T00:00:00Z', precise: true, expect: [0,1,30,0,0,0,0]}, // 12
{start:'2016-10-31T00:00:00Z', end:'2016-12-30T00:00:00Z', precise: false, expect: [0,1,30,0,0,0,0]}, // 13
{start:'2016-10-31T00:00:01Z', end:'2016-12-30T00:00:00Z', precise: true, expect: [0,1,29,23,59,59,0]}, // 14
{start:'2016-10-31T00:00:01Z', end:'2016-12-30T00:00:00Z', precise: false, expect: [0,1,30,0,0,0,0]}, // 15
{start:'2016-10-31T00:00:00Z', end:'2016-12-31T00:00:00Z', precise: true, expect: [0,2,0,0,0,0,0]}, // 16
{start:'2016-10-31T00:00:00Z', end:'2016-12-31T00:00:00Z', precise: false, expect: [0,2,0,0,0,0,0]}, // 17
{start:'2016-10-31T00:00:00Z', end:'2016-12-01T00:00:00Z', precise: true, expect: [0,1,1,0,0,0,0]}, // 18
{start:'2016-10-31T00:00:00Z', end:'2016-12-01T00:00:00Z', precise: false, expect: [0,1,1,0,0,0,0]}, // 19
{start:'2016-10-31T00:00:01Z', end:'2016-12-01T00:00:00Z', precise: true, expect: [0,1,0,23,59,59,0]}, // 20
{start:'2016-01-31T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: false, expect: [0,1,2,0,0,0,0]}, // 21
{start:'2016-01-31T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: true, expect: [0,1,1,23,59,59,0]}, // 22
{start:'2016-01-31T12:00:01Z', end:'2016-03-01T12:00:00Z', precise: false, expect: [0,1,1,0,0,0,0]}, // 23
{start:'2016-01-31T12:00:01Z', end:'2016-03-01T12:00:00Z', precise: true, expect: [0,1,0,23,59,59,0]}, // 24
{start:'2016-01-31T12:00:01Z', end:'2016-03-01T12:00:00Z', precise: false, expect: [0,1,1,0,0,0,0]}, // 25
{start:'2016-01-30T12:00:01Z', end:'2016-03-01T12:00:00Z', precise: true, expect: [0,1,0,23,59,59,0]}, // 26
{start:'2016-01-30T12:00:01Z', end:'2016-03-01T12:00:00Z', precise: false, expect: [0,1,1,0,0,0,0]}, // 27
{start:'2016-01-31T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: true, expect: [0,1,1,23,59,59,0]}, // 28
{start:'2016-01-31T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: false, expect: [0,1,2,0,0,0,0]}, // 29
{start:'2016-01-30T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: true, expect: [0,1,1,23,59,59,0]}, // 30
{start:'2016-01-30T12:00:01Z', end:'2016-03-02T12:00:00Z', precise: false, expect: [0,1,2,0,0,0,0]}, // 31
{start:'2016-03-15T12:00:00Z', end:'2016-04-14T12:00:01Z', precise: true, expect: [0,0,30,0,0,1,0]}, // 32
{start:'2016-03-15T12:00:00Z', end:'2016-04-14T12:00:01Z', precise: false, expect: [0,0,30,0,0,0,0]}, // 33
{start:'2016-07-23T12:00:01Z', end:'2016-09-24T12:00:00Z', precise: true, expect: [0,2,0,23,59,59,0]}, // 34
{start:'2016-07-23T12:00:01Z', end:'2016-09-24T12:00:00Z', precise: false, expect: [0,2,1,0,0,0,0]}, // 35
{start:'2016-07-31T12:00:01Z', end:'2018-07-01T12:00:00Z', precise: true, expect: [1,11,0,23,59,59,0]},
{start:'2016-07-31T12:00:01Z', end:'2018-07-01T12:00:00Z', precise: false, expect: [1,11,1,0,0,0,0]},
{start:'2016-07-01T12:00:01Z', end:'2018-07-31T12:00:00Z', precise: true, expect: [2,0,29,23,59,59,0]},
{start:'2016-07-01T12:00:01Z', end:'2018-07-31T12:00:00Z', precise: false, expect: [2,0,30,0,0,0,0]}
//*/
].forEach(function(obj, i) {
var x = dateDiff(parseISO(obj.start), parseISO(obj.end), obj.precise)
var r = [x.y, x.m, x.d, x.hr, x.min, x.sec, x.ms];
resultHTML.push('<tr><td>'+i+'<td>' + obj.start + '<td>' + obj.end + '<td>' + (obj.precise? 'Y':'') +
'<td>' + (obj.precise? obj.expect : obj.expect.slice(0,3)) + '<td class="' + (sameAs(r, obj.expect)? '':'fail') + '">' +
(obj.precise? r : r.slice(0,3)));
});
document.write(resultHTML.join('') + '</table>');
&#13;
.fail {
background-color: #ffbbbb;
}
table {
font-family: courier, mono-spaced;
font-size: 90%;
border-collapse: collapse;
border-top: 1px solid #bbbbbb;
border-left: 1px solid #bbbbbb;
}
td, th {
border-bottom: 1px solid #bbbbbb;
border-right: 1px solid #bbbbbb;
}
td {
padding: 2px 5px 2px 5px;
}
td:nth-Child(3) {
text-align: center;
}
&#13;