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