-3

I am looking for a JS library/utility/function where you give it num of month and it returns the human readable version of it.

I have almost done it in Vanilla JS but now I figure out there are a lot of edge cases that I do not want to re-invent the wheel.

Example

func(3) => "3 Months"
func(1) => "1 Month" // singular
func(0.1) => "1 Week"
func(0.25) => "2 Weeks"
func(13) => "1 year and 1 month"
func(14) => "1 year and 2 months"
func(14.25) => "1 year, 2 months and two weeks"
.
..
...etc

Problem Statement: I don't want to re-invent the wheel and see if there are any library that is currently doing date conversion as above.

Jamie Jamier
  • 459
  • 6
  • 18

3 Answers3

1

Using the moment.js:

Date.getFormattedDateDiff = function (date1, date2) {
  var b = moment(date1),
    a = moment(date2),
    intervals = ['year', 'month', 'week', 'day'],
    out = [];

  for (var i = 0; i < intervals.length; i++) {
    var diff = a.diff(b, intervals[i]);
    b.add(diff, intervals[i]);
    if (diff == 0)
      continue;
    out.push(diff + ' ' + intervals[i] + (diff > 1 ? "s" : ""));
  }
  return out.join(', ');
};

function OutputMonths(months) {
  var newYear = new Date(new Date().getFullYear(), 0, 1);
  var days = (months % 1) * 30.4167;

  var newDate = new Date(newYear.getTime());
  newDate.setMonth(newDate.getMonth() + months);
  newDate.setDate(newDate.getDate() + days);

  console.log('Number of months: ' + Date.getFormattedDateDiff(newYear, newDate));
}

OutputMonths(3);
OutputMonths(1);
OutputMonths(0.1);
OutputMonths(0.25);
OutputMonths(13);
OutputMonths(14);
OutputMonths(14.25);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
Andrew Arthur
  • 1,563
  • 2
  • 11
  • 17
1

It depends on what your version of a 'human readable version' is. You could simply convert your month number to days and work from there. Since you included years, months and weeks in your example cases all you'd need is this.

function func(months) {
    let days = months * 30.5; // Average days in a month
    let y = 0, m = 0, w = 0;
    while (days >= 365) {y++;days -= 365;}
    while (days >= 30.5) {m++;days -= 30.5;}
    while (days >= 7) {w++;days -= 7;}
    let out = 
        (y ? (`${y} Year` + (y > 1 ? "s " : " ")) : "") +
        (m ? (`${m} Month` + (m > 1 ? "s " : " ")) : "") +
        (w ? (`${w} Week` + (w > 1 ? "s " : " ")) : "");
    console.log(out);
}
func(10);
func(3);
func(1);
func(0.1);
func(0.25);
func(13);
func(14);
func(14.25);
Simpler is always better, specially when it's such a simple problem. You don't want to bloat your application with a library just for this.
0

console.log(moment.duration(40, 'months').toISOString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>

momentjs duration use

Have a look at https://github.com/codebox/moment-precise-range also

Ziaullhaq Savanur
  • 1,848
  • 2
  • 17
  • 20