仅使用Date.valueOf()

时间:2016-04-04 05:00:20

标签: javascript date

我试图在JavaScript中获取最接近绝对年份的毫秒值,仅回复JavaScript Date对象的valueOf()方法。

例如:今天是2016年4月4日星期一上午12:50。所以我正在寻找最接近的绝对年份(过去)。 2016年1月1日00:00 am。

这是我的代码:

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年以来和当年年初开始的毫秒数,仅依靠数学?

3 个答案:

答案 0 :(得分:1)

你需要应对闰年,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);
});
&#13;
body {
  font-family: courier, mono-space;
  font-size: 90%
}
&#13;
&#13;
&#13;

修改

这是一个非循环解决方案。它如上所述在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;
}

答案 1 :(得分:1)

这应该可以解决问题:

var d = new Date(new Date().getFullYear(), 0);
d.valueOf(); // > 1451634391371 (ms)

答案 2 :(得分:0)

由于以下假设,你的逻辑不起作用

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

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