最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do I convert a decimal year value into a Date in Javascript? - Stack Overflow

programmeradmin3浏览0评论

OK, this is basically a Javascript version of How can I convert a decimal year value into a Date in Ruby? and not exactly a duplicate of Javascript function to convert decimal years value into years, months and days

Input:

2015.0596924

Desired output:

January 22, 2015

I have solved it (see below), but I expect (just like the Ruby version of this question) that there is a better way.

OK, this is basically a Javascript version of How can I convert a decimal year value into a Date in Ruby? and not exactly a duplicate of Javascript function to convert decimal years value into years, months and days

Input:

2015.0596924

Desired output:

January 22, 2015

I have solved it (see below), but I expect (just like the Ruby version of this question) that there is a better way.

Share Improve this question edited May 23, 2017 at 12:14 CommunityBot 11 silver badge asked Apr 1, 2015 at 20:30 Alien Life FormAlien Life Form 5911 gold badge7 silver badges15 bronze badges 4
  • Please define "decimal year". How would a conversion work? Where do you get your input from? Is there any specification? – Bergi Commented Apr 1, 2015 at 20:45
  • By "decimal year" I mean a decimal that tells you the year and how far towards the next year you are... so 2014.99999 would be right before you kiss your baby on New Years 2015 and 2015.00001 would be right after the kiss ends. 2015.5 would be directly in the middle of the year. – Alien Life Form Commented Apr 1, 2015 at 21:21
  • Ok, so year + 1 would not necessarily the same day as year. Odd. But it seems you can do something similar simple to the ruby code in js. – Bergi Commented Apr 1, 2015 at 21:59
  • Only if it were a leap year vs. non-leap year would it be different. Ruby's Date method allows you to give it a decimal year. Javascript's does not. Looks like the milliseconds method is the most succinct way. – Alien Life Form Commented Apr 2, 2015 at 23:01
Add a ment  | 

4 Answers 4

Reset to default 3

The other solution would be:

  1. Create date for given year (integer part)
  2. Calculate days from reminder (decimal part) and convert to milliseconds
  3. Add milliseconds to (1)

In script:

function leapYear(year) {
    return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
};

function convertDecimalDate(decimalDate) {
    var year = parseInt(decimalDate);
    var reminder = decimalDate - year;
    var daysPerYear = leapYear(year) ? 366 : 365;
    var miliseconds = reminder * daysPerYear * 24 * 60 * 60 * 1000;
    var yearDate = new Date(year, 0, 1);
    return new Date(yearDate.getTime() + miliseconds);
}

var date = convertDecimalDate(2015.0596924);
console.log(date);

You can play with it on this Fiddle.

JavaScript will resolve the dates for you if you add too much time. See demonstration below. The solution below doesn't calculate the leap year based on the algorithm, but takes next year's date and subtracts it from this year. This assumes that the JavaScript specification properly calculates leap years.

See Mozilla Docs for more info.

function decimalDateToJsDate(time) {
  var year = Math.floor(time);
  var thisYear = new Date(year, 0, 1);
  var nextYear = new Date(year + 1, 0, 1);
  var millisecondsInYear = nextYear.getTime() - thisYear.getTime();
  var deltaTime = Math.ceil((time - year) * millisecondsInYear);
  thisYear.setMilliseconds(deltaTime);
  return thisYear;
}

document.getElementById("output").innerHTML = decimalDateToJsDate(2015.0596924);
<pre id="output"></pre>

function leapYear (year){
  return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

function getMonthAndDayFromDayOfYear(dayOfYear, year){
  var daysInMonthArray = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  if (leapYear(year)) { daysInMonthArray[2] = 29; }

  var daysLeft = dayOfYear;
  var month = 0;
  for (i=0; i<daysInMonthArray.length; i++) {
    var daysInThisMonth = daysInMonthArray[i];
    if (daysLeft > daysInThisMonth) {
      month += 1;
      daysLeft -= daysInThisMonth;
    } else {
      break;
    }
  }
  return { month: month, day: daysLeft };
}

function convertDecimalDate(decimalDate){
  decimalDate = parseFloat(decimalDate);
  var year = parseInt(decimalDate); // Get just the integer part for the year
  var daysPerYear = leapYear(year) ? 366 : 365; // Set days per year based on leap year or not
  var decimalYear = decimalDate - year; // A decimal representing portion of the year left
  var dayOfYear = Math.ceil(decimalYear * daysPerYear); // day of Year: 1 to 355 (or 366)
  var md = getMonthAndDayFromDayOfYear(dayOfYear, year);
  var day = md['day'];
  var month = md['month'];
  return new Date(year,month,day);
}

var date = convertDecimalDate(2015.0596924);

I thought I would try my hand at a minimal solution. Your fractional date returns January 21, 2015.

leapyear code inspired by How to find leap year programmatically in C

leapyear=year=>!(year%4 || year%400 && !(year%100))

decdate=year=>new Date(year, 0, year % 1 * (365 + leapyear(year)))

console.log(decdate(2015.0596924).toLocaleDateString('en-us',{ month:'long', day:'numeric', year:'numeric'}))

发布评论

评论列表(0)

  1. 暂无评论