我试图在JavaScript中获得最近的绝对年份的毫秒值,只对JavaScriptDate对象的valueOf()
方法进行回复。
例如:今天是2016年4月4日星期一上午12:50。因此,我正在寻找(过去)最近的绝对年份。2016年1月1日凌晨00:00。
这是我的代码:
var ms_per_year = 31536000000;
var now = new Date().valueOf();
var mod_year = now % ms_per_year;
var nearest_absolute_year = now - mod_year;
console.log(new Date(nearest_absolute_year));
// Sun Dec 20 2015 19:00:00 GMT-0500 (EST)
console.log(new Date(Date.parse('2016 1 1 00:00:00')));
// Fri Jan 01 2016 00:00:00 GMT-0500 (EST)
我希望两个打印的日期是相同的,因为它们有分钟:
var ms_per_minute = 60 * 1000;
var now = new Date().valueOf();
var mod_minute = now % ms_per_minute;
var nearest_absolute_minute = now - mod_minute;
console.log(new Date(nearest_absolute_minute));
// Mon Apr 04 2016 00:57:00 GMT-0400 (EDT)
console.log(new Date(Date.parse('2016 4 4 00:57:00')));
// Mon Apr 04 2016 00:57:00 GMT-0400 (EDT)
如果不使用Date.parse(),仅依靠数学,我如何计算自1970年以来到今年年初的毫秒数?
你需要处理闰年,Himanshu正在寻找一个优雅的解决方案,一个简单的循环就可以了,但效率不高:
/* @returns {number} time value for start of current year
** Don't use Date methods
** Assumes current time is after epoch (1970-01-01T00:00:00Z)
*/
function getStartOfYear(timeValue) {
var timeValue = timeValue || Date.now();
var accumulatedTime = 0;
var day = 8.64e7;
var year = 1970;
var msForYear = 365*day; // ms for 1970
function isLeap(n) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
// Continue while adding ms for current year won't go past limit
while ((accumulatedTime + msForYear) < timeValue) {
// Add time for current year
accumulatedTime += msForYear;
// Calculate time for next year
msForYear = (isLeap(++year)? 366:365) * day;
}
// Return accumulated time
return accumulatedTime;
}
// Tests
['2010','2011','2012','2013','2014','2015','2016','2017'].forEach(function(y){
//Generate time value away from start of year
var startOfYear = new Date(getStartOfYear(new Date(y,3).getTime() + 23000));
document.write('<br>UTC start of year: ' + startOfYear.toISOString());
startOfYear.setMinutes(startOfYear.getMinutes() + startOfYear.getTimezoneOffset());
document.write('<br>Local start of year: ' + startOfYear);
});
body {
font-family: courier, mono-space;
font-size: 90%
}
编辑
这是一个非循环的解决方案。如上所述,它在UTC工作,但也可以根据建议调整为本地。
function getStartOfYear(timeValue) {
timeValue = +timeValue || Date.now();
// ms for one day
var day = 8.64e7;
// ms for standard year
var year = 365 * day
// ms for leap block
var leapBlock = year * 4 + day;
// Use 1969-01-01T00:00:00Z as epoch
timeValue += year;
// Accumulate time
var accumulatedTime = 0;
accumulatedTime += Math.floor(timeValue / leapBlock) * leapBlock;
accumulatedTime += Math.floor((timeValue % leapBlock) / year) * year;
// Reset epoch to 1970-01-01T00:00:00Z and return time value
return accumulatedTime - year;
}
如果你想要模糊但简洁的代码,试试:
function getStartOfYear(timeValue) {
timeValue = +timeValue || Date.now();
var day = 8.64e7, year = 365 * day, leapBlock = year * 4 + day, accumulatedTime = 0;
return ((timeValue + year) / leapBlock | 0) * leapBlock + ((timeValue + year) % leapBlock / year | 0) * year - year;
}
这应该可以做到:
var d = new Date(new Date().getFullYear(), 0);
d.valueOf(); // > 1451634391371 (ms)
由于以下假设,您的逻辑不起作用
var ms_per_year = 31536000000
对于365天的一年来说,这是毫秒的正确值,但你忘了将闰年考虑在内。
以下代码将帮助
var ms_per_year = 31536000000;
var ms_per_day = 86400000;
var now = new Date().valueOf();
var mod_year = now % ms_per_year;
var year = Math.floor(now/ms_per_year);
var leap_years = Math.floor(year/4);
var nearest_absolute_year = now - mod_year;
var actual_value = nearest_absolute_year + (leap_years*ms_per_day);
console.log(new Date(actual_value));
如果你发现任何错误,请纠正我。