TimeString.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * Exports
  3. */
  4. module.exports = parseTimestring;
  5. /**
  6. * Default options to use when parsing a timestring
  7. *
  8. * @type {Object}
  9. */
  10. const DEFAULT_OPTS = {
  11. hoursPerDay: 24,
  12. daysPerWeek: 7,
  13. weeksPerMonth: 4,
  14. monthsPerYear: 12,
  15. daysPerYear: 365.25,
  16. };
  17. /**
  18. * Map of accepted strings to unit
  19. *
  20. * @type {Object}
  21. */
  22. const UNIT_MAP = {
  23. ms: ["ms", "milli", "millisecond", "milliseconds"],
  24. s: ["s", "sec", "secs", "second", "seconds"],
  25. m: ["m", "min", "mins", "minute", "minutes"],
  26. h: ["h", "hr", "hrs", "hour", "hours"],
  27. d: ["d", "day", "days"],
  28. w: ["w", "week", "weeks"],
  29. mth: ["mon", "mth", "mths", "month", "months"],
  30. y: ["y", "yr", "yrs", "year", "years"],
  31. };
  32. /**
  33. * Parse a timestring
  34. *
  35. * @param {string} string
  36. * @param {string} returnUnit
  37. * @param {Object} opts
  38. * @returns {number}
  39. */
  40. function parseTimestring(string, returnUnit, opts) {
  41. opts = Object.assign({}, DEFAULT_OPTS, opts || {});
  42. let totalSeconds = 0;
  43. const unitValues = getUnitValues(opts);
  44. const groups = string
  45. .toLowerCase()
  46. .replace(/[^.\w+-]+/g, "")
  47. .match(/[-+]?[0-9.]+[a-z]+/g);
  48. if (groups === null) {
  49. throw new Error(`The string [${string}] could not be parsed by timestring`);
  50. }
  51. groups.forEach((group) => {
  52. const value = group.match(/[0-9.]+/g)[0];
  53. const unit = group.match(/[a-z]+/g)[0];
  54. totalSeconds += getSeconds(value, unit, unitValues);
  55. });
  56. if (returnUnit) {
  57. return convert(totalSeconds, returnUnit, unitValues);
  58. }
  59. return totalSeconds;
  60. }
  61. /**
  62. * Get unit values based on the passed options
  63. *
  64. * @param {Object} opts
  65. * @returns {Object}
  66. */
  67. function getUnitValues(opts) {
  68. const unitValues = {
  69. ms: 0.001,
  70. s: 1,
  71. m: 60,
  72. h: 3600,
  73. };
  74. unitValues.d = opts.hoursPerDay * unitValues.h;
  75. unitValues.w = opts.daysPerWeek * unitValues.d;
  76. unitValues.mth = (opts.daysPerYear / opts.monthsPerYear) * unitValues.d;
  77. unitValues.y = opts.daysPerYear * unitValues.d;
  78. return unitValues;
  79. }
  80. /**
  81. * Get the key for a unit
  82. *
  83. * @param {string} unit
  84. * @returns {string}
  85. */
  86. function getUnitKey(unit) {
  87. for (const key of Object.keys(UNIT_MAP)) {
  88. if (UNIT_MAP[key].indexOf(unit) > -1) {
  89. return key;
  90. }
  91. }
  92. throw new Error(`The unit [${unit}] is not supported by timestring`);
  93. }
  94. /**
  95. * Get the number of seconds for a value, based on the unit
  96. *
  97. * @param {number} value
  98. * @param {string} unit
  99. * @param {Object} unitValues
  100. * @returns {number}
  101. */
  102. function getSeconds(value, unit, unitValues) {
  103. return value * unitValues[getUnitKey(unit)];
  104. }
  105. /**
  106. * Convert a value from its existing unit to a new unit
  107. *
  108. * @param {number} value
  109. * @param {string} unit
  110. * @param {Object} unitValues
  111. * @returns {number}
  112. */
  113. function convert(value, unit, unitValues) {
  114. return value / unitValues[getUnitKey(unit)];
  115. }