Skip to content

Instantly share code, notes, and snippets.

@PantheraRed
Last active July 21, 2023 11:13
Show Gist options
  • Save PantheraRed/2e65c48cdfa6fba49473913300cc8b12 to your computer and use it in GitHub Desktop.
Save PantheraRed/2e65c48cdfa6fba49473913300cc8b12 to your computer and use it in GitHub Desktop.
Convert milliseconds to years, months, days, hours, minutes & seconds in JavaScript.
'use strict'; // Remove this if you don't wish to use strict mode
function ms(t) {
let year,
month,
day,
hour,
minute,
second;
second = Math.floor(t / 1000);
minute = Math.floor(second / 60);
second = second % 60;
hour = Math.floor(minute / 60);
minute = minute % 60;
day = Math.floor(hour / 24);
hour = hour % 24;
month = Math.floor(day / 30);
day = day % 30;
year = Math.floor(month / 12);
month = month % 12;
return { year, month, day, hour, minute, second };
}
module.exports = ms;
// Usage: ms(1627297964704) returns { year: 52, month: 3, day: 24, hour: 11, minute: 12, second: 44 }
@melroy89
Copy link

melroy89 commented Jan 3, 2023

This is not accurate at all.

@PantheraRed
Copy link
Author

Hello @Danger89, mind elaborating? Would like to correct this gist. :)

@melroy89
Copy link

melroy89 commented Jan 3, 2023

@PantheraRed Sure! So calculating the time duration between two dates is a bit sticky. Especially if they are far apart from each other. In your specific ms() function this can easily deviate in months of errors.

Background story & idea

Again, that is because a timestamp by itself isn't really easy to convert directly to a year, months and day of a difference. At least not accurately. After all, not every year as the same amount of days. And not every month has the same amount of days.

You could try to use the math that is explained here for longeterm conversion accuracy (but it will never be a golden solution, but might improve the accuracy):

https://github.com/moment/luxon/blob/master/docs/math.md#casual-vs-longterm-conversion-accuracy

(See the table)

My current Solution

Currently I'm using the Luxon library instead, with two Luxon DateTime objects and then using the diff() method.

An example for a date: 2012-03-13 6:30:24 PM UTC, see ISO string below. This would result in 1331663424000 epoch timestamp in milliseconds. I will later come back to this epoch timestamp.

const { DateTime } = require('luxon'); // Importing Luxon

const start = DateTime.fromISO('2012-03-13T18:30:24.000Z'); // Just an example time from the past, using the ISO standard
const end = DateTime.now(); // Current time
const diff = end.diff(start, ['years', 'months', 'days', 'hours', 'minutes', 'seconds', 'milliseconds'])

// Let's print the difference object to a Javascript object: https://moment.github.io/luxon/api-docs/index.html#datetimetoobject
console.log(diff.toObject())

This should give you the following JS object in the console (this is correct. You can count the years, months and days manually if you would like):

{
  years: 10,
  months: 9,
  days: 21,
  hours: 3,
  minutes: 27,
  seconds: 38,
  milliseconds: 389
}

Using the diff() from Luxon is the only way to have a result really accurately and thus correct.

Bonus - Testing your function

Let's compare that to your function. I will first calculate the diff of 1331663424000 with the current timestamp in ms, that would be:

Date.now() - 1331663424000

That results into: 341119598771. Now I will use your function using the 341119598771 as input:

ms(341119598771)

Your function returns:

{ year: 10, month: 11, day: 18, hour: 3, minute: 26, second: 38 }

That is an error of around 2 months!?


I hope this helps you and others.

@PantheraRed
Copy link
Author

@Danger89 Thank you for such a great explanation. This will definitely help me improve the gist in future. I personally found luxon a better alternative.

@melroy89
Copy link

melroy89 commented Jan 6, 2023

As I stated in my explanation, I'm using Luxon now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment