UNPKG

2.94 kBJavaScriptView Raw
1/* eslint-disable radix */
2const moment = require('moment');
3
4// the official units recognized by the momentjs
5const secondUnit = 'second';
6const minuteUnit = 'minute';
7const hourUnit = 'hour';
8const dayUnit = 'day';
9
10/** allowed CLI->time unit bindings */
11const timeReprMap = {
12 s: secondUnit,
13 sec: secondUnit,
14 second: secondUnit,
15 seconds: secondUnit,
16 m: minuteUnit,
17 min: minuteUnit,
18 mins: minuteUnit,
19 minute: minuteUnit,
20 minutes: minuteUnit,
21 h: hourUnit,
22 hr: hourUnit,
23 hour: hourUnit,
24 hours: hourUnit,
25 d: dayUnit,
26 day: dayUnit,
27 days: dayUnit,
28};
29
30// simple regex which verifies if a certain timestring
31// is only composed of numbers
32const onlyNumeric = /^[0-9]+$/g;
33
34const offsetFormat = /^[0-9]+[a-z]+$/g;
35
36/**
37 * Converts a offset format timestring to its representation
38 * in milliseconds.
39 *
40 * Valid examples:
41 *
42 * '2h'
43 * '3hours'
44 * '4w'
45 * '5days'
46 * etc...
47 *
48 * @param {string} offset - string representing offset time
49 * @return {integer} - the string offset value in 'ms'
50 */
51const fromOffset = function fromOffset(offset) {
52 // match the first occurrence of numbers until but not
53 // including the first non number
54 const timePart = offset.match(/[0-9]+.*?(?=[^0-9])/);
55 const realTime = parseInt(timePart);
56 // not even sure this path can be reached due to the regex
57 if (isNaN(realTime)) {
58 throw new Error(`Invalid offset format "${offset}", time portion was ${realTime}`);
59 }
60 // match the first(and only) group of lowercase letters
61 const textPart = offset.match(/[a-z]+/);
62 // does the user time format string have a registered mapping
63 const textRepr = timeReprMap[textPart];
64 if (!textRepr || !textPart) {
65 throw new Error(`Invalid offset format, unknown unit "${offset.slice(timePart.toString().length, offset.length)}"`);
66 }
67 // current time and then subtract the user offset
68 const calculatedTime = moment();
69 calculatedTime.subtract(realTime, textRepr);
70 return calculatedTime;
71};
72
73/**
74 * Parses the provided timestring if it is one of the four
75 * acceptable formats(RFC822, ISO8061, unix timestamp, and
76 * finally 'simple time format').
77 *
78 * @param {string} timeString - timestamp to parse
79 *
80 * @returns {number} - unix time parsed from a timestamp
81 */
82const parseTimeString = function parseTimeString(timeString) {
83 const attemptISO = moment(timeString, moment.ISO_8601);
84 // TODO(Ry): add debug log that shows final time in ms
85 if (onlyNumeric.test(timeString)) {
86 const parsedNumber = parseInt(timeString.replace('.', ''));
87 const timestamp = moment(parsedNumber);
88 if (timestamp.isValid()) {
89 return timestamp;
90 }
91 throw new Error(`Invalid numeric timestamp format "${timeString}"`);
92 } else if (attemptISO.isValid()) {
93 return attemptISO;
94 } else if (offsetFormat.test(timeString)) {
95 return fromOffset(timeString);
96 }
97 throw new Error(`Invalid time format "${timeString}"`);
98};
99
100module.exports = {
101 parseTimeString,
102};