github.com/aminovpavel/nomad@v0.11.8/ui/app/utils/format-duration.js (about)

     1  import moment from 'moment';
     2  import { pluralize } from 'ember-inflector';
     3  
     4  /**
     5   * Metadata for all unit types
     6   * name: identifier for the unit. Also maps to moment methods when applicable
     7   * suffix: the preferred suffix for a unit
     8   * inMoment: whether or not moment can be used to compute this unit value
     9   * pluralizable: whether or not this suffix can be pluralized
    10   * longSuffix: the suffix to use instead of suffix when longForm is true
    11   */
    12  const allUnits = [
    13    { name: 'years', suffix: 'year', inMoment: true, pluralizable: true },
    14    { name: 'months', suffix: 'month', inMoment: true, pluralizable: true },
    15    { name: 'days', suffix: 'day', inMoment: true, pluralizable: true },
    16    { name: 'hours', suffix: 'h', longSuffix: 'hour', inMoment: true, pluralizable: false },
    17    { name: 'minutes', suffix: 'm', longSuffix: 'minute', inMoment: true, pluralizable: false },
    18    { name: 'seconds', suffix: 's', longSuffix: 'second', inMoment: true, pluralizable: false },
    19    { name: 'milliseconds', suffix: 'ms', inMoment: true, pluralizable: false },
    20    { name: 'microseconds', suffix: 'µs', inMoment: false, pluralizable: false },
    21    { name: 'nanoseconds', suffix: 'ns', inMoment: false, pluralizable: false },
    22  ];
    23  
    24  const pluralizeUnits = (amount, unit, longForm) => {
    25    let suffix;
    26  
    27    if (longForm && unit.longSuffix) {
    28      // Long form means always using full words (seconds insteand of s) which means
    29      // pluralization is necessary.
    30      suffix = amount === 1 ? unit.longSuffix : pluralize(unit.longSuffix);
    31    } else {
    32      // In the normal case, only pluralize based on the pluralizable flag
    33      suffix = amount === 1 || !unit.pluralizable ? unit.suffix : pluralize(unit.suffix);
    34    }
    35  
    36    // A space should go between the value and the unit when the unit is a full word
    37    // 300ns vs. 1 hour
    38    const addSpace = unit.pluralizable || (longForm && unit.longSuffix);
    39    return `${amount}${addSpace ? ' ' : ''}${suffix}`;
    40  };
    41  
    42  /**
    43   * Format a Duration at a preferred precision
    44   *
    45   * @param {Number} duration The duration to format
    46   * @param {String} units The units for the duration. Default to nanoseconds.
    47   * @param {Boolean} longForm Whether or not to expand single character suffixes,
    48   *   used to ensure screen readers correctly read units.
    49   */
    50  export default function formatDuration(duration = 0, units = 'ns', longForm = false) {
    51    const durationParts = {};
    52  
    53    // Moment only handles up to millisecond precision.
    54    // Microseconds and nanoseconds need to be handled first,
    55    // then Moment can take over for all larger units.
    56    if (units === 'ns') {
    57      durationParts.nanoseconds = duration % 1000;
    58      durationParts.microseconds = Math.floor((duration % 1000000) / 1000);
    59      duration = Math.floor(duration / 1000000);
    60    } else if (units === 'mms') {
    61      durationParts.microseconds = duration % 1000;
    62      duration = Math.floor(duration / 1000);
    63    }
    64  
    65    let momentUnits = units;
    66    if (units === 'ns' || units === 'mms') {
    67      momentUnits = 'ms';
    68    }
    69    const momentDuration = moment.duration(duration, momentUnits);
    70  
    71    // Get the count of each time unit that Moment handles
    72    allUnits
    73      .filterBy('inMoment')
    74      .mapBy('name')
    75      .forEach(unit => {
    76        durationParts[unit] = momentDuration[unit]();
    77      });
    78  
    79    // Format each time time bucket as a string
    80    // e.g., { years: 5, seconds: 30 } -> [ '5 years', '30s' ]
    81    const displayParts = allUnits.reduce((parts, unitType) => {
    82      if (durationParts[unitType.name]) {
    83        const count = durationParts[unitType.name];
    84        parts.push(pluralizeUnits(count, unitType, longForm));
    85      }
    86      return parts;
    87    }, []);
    88  
    89    if (displayParts.length) {
    90      return displayParts.join(' ');
    91    }
    92  
    93    // When the duration is 0, show 0 in terms of `units`
    94    return pluralizeUnits(0, allUnits.findBy('suffix', units), longForm);
    95  }