1
\$\begingroup\$

This is small utility class I made format.utility.ts. There are some other one off utility methods in here I removed for this. The one in question is duration()

class Duration {
  constructor(public value: number, public name: string) { }
}

export class FormatUtility {

  private static durations: Array<Duration> = [
    new Duration(60, 'seconds'),
    new Duration(60, 'minutes'),
    new Duration(24, 'hours'),
    new Duration(7, 'days'),
    new Duration(4, 'weeks'),
    new Duration(12, 'months'),
    new Duration(null, 'years')
  ]

  public static duration(time: number, interval?: string, duration?: Duration): string {
    time = Math.abs(time);
    duration = duration == null ? (interval == null ? this.durations[0] : this.durations.find(x => x.name == interval)) : duration;

    if (!duration)
      throw new Error(`The interval specified (${interval}) is unknown`);

    if (!duration.value || time <= duration.value)
      return Math.round(time) + ' ' + duration.name;

    let i: number = this.durations.findIndex(x => x.name == duration.name);

    return this.duration(time / duration.value, null, this.durations[i+1]);

  }



}

tests/examples:

FormatUtility.duration(12)
// '12 seconds'

FormatUtility.duration(87)
// '1 minutes'

FormatUtility.duration(112, 'hours')
// '5 days'

FormatUtility.duration(4585, 'minutes')
// '3 days'

FormatUtility.duration(23999999, 'hours')
// '2976 years'

The point of this is I have a lot of places in my app where I have display a duration like '12 days ago' or '6 minutes ago' but there are no requirements on the specific interval to use. They wanted to always have 'the most human readable interval for the specific time'. So I came up with this utility and method. Using moment.js elsewhere I get the duration between two dates in seconds and then call FormatUtility.duration(seconds) and have it generate that human readable label for me.

For the review, I'm notoriously awful with recursion which is why I chose to use it here. Looking for general feedback on Typescript usage, vanilla JS, recursion, and whatever else. Is there a better way? Or changes to make this better?

If anyone sees red flags, please let me know.

\$\endgroup\$
  • 2
    \$\begingroup\$ Since you are using moment.js already, is there some reason you don't want to use fromNow? docs \$\endgroup\$ – Gerrit0 Aug 22 '17 at 23:28
  • \$\begingroup\$ I agree with @Gerrit0 there's no need to write a custom function. Just use a built-in one: momentjs.com/docs/#/displaying/fromnow \$\endgroup\$ – Igor Soloydenko Sep 5 '17 at 20:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.