JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
JavaScript
class Duration {
constructor({
years = 0,
months = 0,
weeks = 0,
days = 0,
hours = 0,
minutes = 0,
seconds = 0
}) {
this.years = years
this.months = months
this.days = days + 7 * weeks
this.hours = hours
this.minutes = minutes
this.seconds = seconds
}
static fromLiteral(str) {
const tokens = str
.split(/(\d+)/g)
.map(s => s.trim())
.filter(s => s !== '')
.map(item => {
const unitAliases = {
years: 'years',
year: 'years',
y: 'years',
months: 'months',
month: 'months',
weeks: 'weeks',
week: 'weeks',
w: 'weeks',
days: 'days',
day: 'days',
d: 'days',
hours: 'hours',
hour: 'hours',
h: 'hours',
minutes: 'minutes',
minute: 'minutes',
mins: 'minutes',
min: 'minutes',
m: 'minutes',
seconds: 'seconds',
second: 'seconds',
secs: 'seconds',
sec: 'seconds',
s: 'seconds'
}
if (unitAliases[item]) {
return { type: 'unit', unit: unitAliases[item] }
}
return { type: 'number', num: parseInt(item, 10) }
})
if (tokens.length % 2 !== 0) return null
let values = { years: 0, months: 0, days: 0, hours: 0, minutes: 0, seconds: 0 }
let usedUnits = []
for (let i = 0; i < tokens.length; i += 2) {
if (tokens[i].type !== 'number') return null
if (tokens[i + 1].type !== 'unit') return null
const unit = tokens[i + 1].unit
const num = tokens[i].num
// Reject if a single unit is being defined twice
if (usedUnits.includes(unit)) {
return null
}
if (unit === 'weeks') {
values.days += 7 * num
} else {
values[unit] += num
}
usedUnits.push(unit)
}
return new this(values)
...