[Pending] Calculate Years and Months since a Specific Date

I am trying to come up with a simple solution to:

current date - indicated date with format “January 4, 2018” = years and months since the indicated date.

I looked at the Datejs but I was unable to figure out how to use it to do a simple math date calculation.

I came up with this but I am not sure if this is the way to go. Suggestions are welcomed.

var dPast = 'January 4, 2018'
var d1 = new Date(); //"now"
var d2 = new Date(dPast);
var dCalc = Math.abs((d1-d2)/31556952000);   // difference in milliseconds
var diff = Math.round(10 * dCalc)/10;   // difference in years rounded to tenth

alert('It has been ' + diff + ' years since ' + dPast);

Edit: Solved. Here is a solution that I got from a Reddit user:

var dPast = 'January 4, 2018'
var d1 = new Date(); //"now"
var d2 = new Date(dPast);

var years = d1.getYear() - d2.getYear()
var months = d1.getMonth() - d2.getMonth()
alert(`It has been ${years} years and ${months} months`)

You won’t like that solution if today’s month is “before” dPast’s month. Try it with

dPast = 'December 4, 2017';

and you’ll get “It has been 3 years and -4 months.” Which is true in a sense but probably not what you’re looking for.

If you think you’ll do this kind of date math ever again, I suggest installing the Dayjs library. Download the dayjs.min.js file from the JSDelivr site and save it to the Drafts/Library/Scripts folder in iCloud. With that library in place, you can do stuff like this:

require('dayjs.min.js');

let dPast = 'December 4, 2017';
let d1 = dayjs();
let d2 = dayjs(dPast);

let m = Math.round(d1.diff(d2, 'month', true));

let y = Math.floor(m/12);
if (y == 0) {
  alert(`\n${m} months since ${dPast}`);
}
else {
  m = m % 12;
  if (m == 0) {
    alert(`${y} years since ${dPast}`);
  }
  else {
    alert(`${y} years, ${m} months since ${dPast}`);
  }
}

The important part is the line

let m = Math.round(d1.diff(d2, 'month', true));

This first calculates the difference between the two dates in months, including fractional months. It then rounds to the nearest month.

The rest of the script is just some fiddling with the output. The “years” part is omitted from the output if the difference is less than a year and the “months” part is omitted if the difference is a whole number of years.

2 Likes

@drdrang Thank you. The final push for me to starting learning JavasScript, was after listening to your last episode on Mac Power Users. Glad to see you in the forums. Your code was a step up as I wanted to keep things simple as a beginner. However, I went step by step to understand it. I will leave a footprint here for my own reference and for anyone in the future.

/*********
Day.js is a minimalist JavaScript library that parses, validates, manipulates, and displays dates and times for modern browsers with a largely Moment.js-compatible API.

Step 1: Download the dayjs.min.js file from the JSDelivr site: https://www.jsdelivr.com/package/npm/dayjs

Step 2 : Save the downloaded file to the Drafts/Library/Scripts folder in iCloud. 
*/

require('dayjs.min.js'); // Tell Drafts to use Dayjs script

let dPast = 'December 4, 2017'; // set the date from the past
let d1 = dayjs(); // tell Dayjs to parse the date
let d2 = dayjs(dPast); // set the current date

/******
* Math.round() - is a function that is used to return a number rounded to the nearest integer (whole) value.

* To get the difference in months, pass the month as the second argument. By default, dayjs#diff will truncate the result to zero decimal places, returning an integer. If you want a floating point number, pass true as the third argument.

*Read more: https://day.js.org/docs/en/display/difference#docsNav
*/

let m = Math.round(d1.diff(d2, 'month', true));

/******
* Divide the number of months (obtained earlier) by 12 to see how many years. This number will be rounded to an integer (whole number). If the result is less than 1 (years) the rounded number will be set to 0. For example 11/12 = 0.916666667 This will be rounded to 0.
*/

let y = Math.floor(m/12); 
if (y == 0) {
  alert(`\n${m} months since ${dPast}`); // Alert that "x" number of months but no years have passed since the indicated date.
}
/* Remainder
An amount left over after division (happens when the first number does not divide exactly by the other). Example: 19 cannot be divided exactly by 5. The closest you can get without going over is 3 x 5 = 15, which is 4 less than 19. So 4 is the remainder.

In JavaScript, the remainder operator (%) returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend.
*/
else {
  m = m % 12;
  if (m == 0) {
    alert(`${y} years since ${dPast}`); //If the remainder is 0 than a whole year(s) have passed since the indicated date but no months.
  }
  else {
    alert(`${y} years, ${m} months since ${dPast}`); // Years and months since the indicated date.
  }
}
1 Like

I made further improvements to the script to convert numbers into words. Sharing in case anyone else needs this.

require('dayjs.min.js');

let dPast = draft.content.match(/Loss:\s*(\w+ \d{1,2}, \d{4})/)[1];
let d1 = dayjs();
let d2 = dayjs(dPast);

var m = Math.round(d1.diff(d2, 'month', true));
var y = Math.floor(m/12);

//Funciton - Convert numebrs to words

function numeral(number){
   var numbers = ['zero','one','two','three','four','five','six','seven','eight','nine','ten','eleven'];
   return numbers[number]
}

// Convert singular to plural

y == 1 ? yearWord = 'year' : yearWord = 'years';
m % 12 == 1 ? monthWord = 'month' : monthWord = 'months';

if (y == 0) {
    var month = numeral(m);
    var timeSince = (month + ' ' + monthWord)
}
else {
  m = m % 12;
  if (m == 0) {
    var year = numeral(y);
    var timeSince = (year + ' ' + yearWord);
  }
  else {
    var year = numeral(y);
    var month = numeral(m);
    var timeSince = (year + ' ' + yearWord + ' and ' + month + ' ' + monthWord);
  }
}

editor.setSelectedText(timeSince)

I like how you decided you didn’t need a general solution to the “numbers into words” problem and built a solution for the small, specific problem at hand. I’m assuming the date of loss will never be more than twelve years ago.

Correct. In my case, I am using the script for writing psychological reports where the date of loss (date of accident) is usually not greater than five years from today.

Both, this is both way over my head and achingly close to a solution I’m looking for! Put simply: I’m trying to build a script that will output the number of days I’ve been alive (as a numeral).

So, I run the action and it does the maths on the number of days since my birth date. Ideally it would then insert that number at various points in a (daily blog) template, at [[x]] as follows:

Day [[x]]
Title: Day [[x]]
Date: [[date]]
Permalink: [[x]]

# Day [[x]]

{>|} 

However, if that’s not possible a simple alert that outputs the number would save me visiting WolframAlpha each day! I could then input the number manually.

Any and all help greatly appreciated. Thanks!

(PS: I have downloaded the days.min.js and installed it in Draft’s Scripts folder.)

I think this action should do what you want.

  • Change the DOB constant in the first step (it’s the only thing in the first step) to be your date of birth.
  • The next step calculates the number of days elapsed and places it in your requested template tag - x.
  • The third step defines your template (above) as a new template tag called newcontent.
  • In the fourth and final step, the newcontent template tag is used to populate a new draft and that draft is loaded into the editor.

It seems like this question is only tangentially related to the original thread in that it is doing a calculation with dates. Unless you have a question about something in the thread, it is usually best to post new questions as new topics. You can always include a link back to any topic that inspired you, or that you looked at but wasn’t quite what you needed. By using new topics and naming the topics well, this can make it much easier for people who might have the same question as you to find it in the future.

Hope that helps.

@slyfox Could we solve your “dateing” (pun intended)