仅使用Date.valueOf()在JavaScript中查找上一年



我试图在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)); 

如果你发现任何错误,请纠正我。

最新更新