Time Representations and Decimal Years

Titles are cool.

I wanted to represent a timespan in terms of decimal years, for no apparent reason. This isn’t the most interesting thing I have to talk about, to be fair.

Anyway, I noticed that there’s a variety of ways to calculate this timespan, specifically the non-integer portion. As always, there’s a naïve way to compute the entire number, namely calculate the difference in milliseconds (or some similarly small unit of time), and divide by the number of milliseconds in a year. How many milliseconds are in a year? That’s a silly question, because years don’t have a constant length. We could use the average, but we’d generally be off.

So we know the root issue is that years have a non-constant length. What does a decimal year represent, then? Just like everything else about our measurement of time, it’s an arbitrary representation. I think it makes the most sense to make the representation continuous - if my decimal year clock says “3.5” and I wait half of this year, it should say “4.0,” and every moment of time should be a continuous and linear representation of those two points in time.

So I’ve established something meaningless here, because that doesn’t get us any closer to an answer. Because the decision is meaningless, here are a few possibilities for calculating the decimal: using average length of a year, using the length of the current year, using the length of the destination year, using a combination of the current and destination years, or using the average/combination lengths of the years between the current and destination years (inclusively or exclusively).

I ended up deciding on the fourth option - using a combination of the current and destination years. First, convert the dates into their absolute decimal years, then take the difference of those decimals.

// date must be a valid date object
function getDecimalYear(date) {
  var year = date.getFullYear(), start = +new Date(year, 0);
  return year + (date - start) / (new Date(year + 1, 0) - start);

function getDecimalAge(birth) {
  var birthDate = new Date(birth);
  if (isNaN(birthDate)) return null;
  return getDecimalYear(new Date()) - getDecimalYear(birthDate);

Edit #

I’ve actually changed my mind, and am opting to use the following:

// precondition: start and end are Date objects
function getDecimalDiff(start, end) {
  var mostRecent = new Date(start), endYear = end.getFullYear();
  if (mostRecent > end) mostRecent.setFullYear(endYear -= 1);
  var subsequent = new Date(mostRecent);
  subsequent.setFullYear(endYear + 1);
  return (endYear - start.getFullYear()) + (end - mostRecent) / (subsequent - mostRecent);

Now read this

Security and Passwords

Security is hard, reflected by the increasing number of security breaches at high-profile services. Most services use a username and password authentication scheme. The username represents identity, and the password verifies that... Continue →