diff --git a/Readme.md b/Readme.md index 5951cfd..490f2ba 100644 --- a/Readme.md +++ b/Readme.md @@ -1,101 +1,65 @@ -# parse-duration [![Build Status](https://travis-ci.org/jkroso/parse-duration.svg?branch=master)](https://travis-ci.org/jkroso/parse-duration) +# parse-duration [![Test](https://github.com/jkroso/parse-duration/actions/workflows/test.yml/badge.svg)](https://github.com/jkroso/parse-duration/actions/workflows/test.yml) - convert a human readable duration to ms - -## Installation +Convert a human readable duration to ms. [![NPM](https://nodei.co/npm/parse-duration.png?mini=true)](https://npmjs.org/package/parse-duration) -then in your app: +## Usage ```js import parse from 'parse-duration' -``` - -or CommonJS: - -```js -var parse = require('parse-duration') -``` - -## API - -### parse(str, format='ms') -Convert `str` to ms - -```js -var ns = parse('1ns') // => 1 / 1e6 -var μs = parse('1μs') // => 1 / 1000 -var ms = parse('1ms') // => 1 -var s = parse('1s') // => ms * 1000 -var m = parse('1m') // => s * 60 -var h = parse('1h') // => m * 60 -var d = parse('1d') // => h * 24 -var w = parse('1w') // => d * 7 -var y = parse('1y') // => d * 365.25 -``` - -It can also handle basic compound expressions - -```js +// parse different time units +let ns = parse('1ns') // => 1 / 1e6 +let μs = parse('1μs') // => 1 / 1000 +let ms = parse('1ms') // => 1 +let s = parse('1s') // => ms * 1000 +let m = parse('1m') // => s * 60 +let h = parse('1h') // => m * 60 +let d = parse('1d') // => h * 24 +let w = parse('1w') // => d * 7 +let y = parse('1y') // => d * 365.25 + +// compound expressions parse('1hr 20mins') // => 1 * h + 20 * m parse('1 hr 20 mins') // => 1 * h + 20 * m -``` -youtube format - -```js +// youtube format parse('1h20m0s') // => 1 * h + 20 * m -``` - -comma seperated numbers -```js +// comma seperated numbers parse('27,681 ns') // => 27681 * ns -``` - -And most other types of noise -```js +// noisy input parse('running length: 1hour:20mins') // => 1 * h + 20 * m -``` -You can even use negatives - -```js +// negatives parse('-1hr 40mins') // => 1 * h + 40 * m -``` -And exponents - -```js +// exponents parse('2e3s') // => 2000 * s -``` -#### Available unit types are: +// custom output format +parse('1hr 20mins', 'm') // => 80 -- nanoseconds (ns) -- microseconds (μs) -- milliseconds (ms) -- seconds (s, sec) -- minutes (m, min) -- hours (h, hr) -- days (d) -- weeks (w, wk) -- months -- years (y, yr) +// add units +parse.unit['μs'] = parse.unit.microsecond +parse('5μs') // => 0.005 +``` -And its easy to add more, including unicode: +## Locales + +Switch the default en locale to another language ([see /locale](/locale)). ```js -parse['сек'] = parse['sec'] -parse('5сек') // => 5000 -``` +import es from 'parse-duration/locale/es.js' +import parse from 'parse-duration' -The output format can also be defined +parse.unit = es -```js -parse('1hr 20mins', 'm') // => 80 +parse('1 hora 20 minutos', 'm') // 80 +parse('1 hour 20 minutes', 'm') // 80 - extends english locale ``` + +
diff --git a/index.d.mts b/index.d.mts deleted file mode 100644 index 64d0774..0000000 --- a/index.d.mts +++ /dev/null @@ -1,4 +0,0 @@ -// ./index.d.mts - -export * from './index.js' -export { default } from './index.js' diff --git a/index.d.ts b/index.d.ts index 4ac42a4..64d0774 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,29 +1,4 @@ -// ./index.d.ts +// ./index.d.mts -declare namespace parse { - /** - * convert `str` to ms - */ - type Units = - 'nanosecond' | 'ns' | - 'µs' | 'μs' | 'us' | 'microsecond' | - 'millisecond' | 'ms' | - 'second' | 'sec' | 's' | - 'minute' | 'min' | 'm' | - 'hour' | 'hr' | 'h' | - 'day' | 'd' | - 'week' | 'wk' | 'w' | - 'month' | 'b' | - 'year' | 'yr' | 'y' -} - -type Parse = { - (input: string, format?: parse.Units): number | null; - [key: string]: number; -} & { - default: Parse -} - -declare const parse: Parse; - -export = parse; +export * from './index.js' +export { default } from './index.js' diff --git a/index.js b/index.js index 6741865..ad25736 100644 --- a/index.js +++ b/index.js @@ -1,53 +1,8 @@ -'use strict' +import en from './locale/en.js' -var durationRE = /(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/uig - -module.exports = parse -// enable default import syntax in typescript -module.exports.default = parse - -/** - * conversion ratios - */ - -parse.year = - parse.yr = - parse.y = 60000 * 60 * 24 * 365.25 - -parse.month = - parse.b = 60000 * 60 * 24 * (365.25 / 12) - -parse.week = - parse.wk = - parse.w = 60000 * 60 * 24 * 7 - -parse.day = - parse.d = 60000 * 60 * 24 - -parse.hour = - parse.hr = - parse.h = 60000 * 60 - -parse.minute = - parse.min = - parse.m = 60000 - -parse.second = - parse.sec = - parse.s = 1000 - -parse.millisecond = - parse.millisec = - parse.ms = 1 - -parse['µs'] = - parse['μs'] = - parse.us = - parse.microsecond = 1 / 1e3 - -parse.nanosecond = - parse.ns = 1 / 1e6 +let durationRE = /(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/uig +parse.unit = en /** * convert `str` to ms @@ -57,32 +12,28 @@ parse.nanosecond = * @return {Number} */ -function parse(str = '', format = 'ms') { - if (!Object.prototype.hasOwnProperty.call(parse, format)) { - throw new TypeError('Invalid format "' + format + '"') - } - - var result = null, prevUnits +export default function parse(str = '', format = 'ms') { + let result = null, prevUnits // ignore commas/placeholders - str = (str + '').replace(/(\d)[,_](\d)/g, '$1$2') - str.replace(durationRE, function (_, n, units) { + str = (str + '') + .replace(/(\d)[_ ](\d)/g, '$1$2') // ignore placeholders + .replaceAll(parse.unit.group, '') // remove group separator + .replaceAll(parse.unit.decimal, '.') // normalize decimal separator + + str.replace(durationRE, (_, n, units) => { // if no units, find next smallest units or fall back to format value (ms) if (!units) { if (prevUnits) { - for (var u in parse) if (parse[u] < prevUnits) { units = u; break } + for (var u in parse.unit) if (parse.unit[u] < prevUnits) { units = u; break } } else units = format } else units = units.toLowerCase() - if (Object.prototype.hasOwnProperty.call(parse, units)) { - units = parse[units] - } else if (Object.prototype.hasOwnProperty.call(parse, units.replace(/s$/, ''))) { - units = parse[units.replace(/s$/, '')] - } else { - units = null - } + + units = parse.unit[units] || parse.unit[units.replace(/s$/, '')] + if (units) result = (result || 0) + Math.abs(parseFloat(n, 10)) * units, prevUnits = units }) - return result && ((result / (parse[format] || 1)) * (str[0] === '-' ? -1 : 1)) + return result && ((result / (parse.unit[format] || 1)) * (str[0] === '-' ? -1 : 1)) } diff --git a/index.mjs b/index.mjs deleted file mode 100644 index f6b829a..0000000 --- a/index.mjs +++ /dev/null @@ -1,81 +0,0 @@ -let durationRE = /(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/uig - - -/** - * conversion ratios - */ - -parse.year = - parse.yr = - parse.y = 60000 * 60 * 24 * 365.25 - -parse.month = - parse.b = 60000 * 60 * 24 * (365.25 / 12) - -parse.week = - parse.wk = - parse.w = 60000 * 60 * 24 * 7 - -parse.day = - parse.d = 60000 * 60 * 24 - -parse.hour = - parse.hr = - parse.h = 60000 * 60 - -parse.minute = - parse.min = - parse.m = 60000 - -parse.second = - parse.sec = - parse.s = 1000 - -parse.millisecond = - parse.millisec = - parse.ms = 1 - -parse['µs'] = - parse['μs'] = - parse.us = - parse.microsecond = 1 / 1e3 - -parse.nanosecond = - parse.ns = 1 / 1e6 - - -/** - * convert `str` to ms - * - * @param {String} str - * @param {String} format - * @return {Number} - */ - -function parse(str = '', format = 'ms') { - var result = null, prevUnits - // ignore commas/placeholders - str = (str + '').replace(/(\d)[,_](\d)/g, '$1$2') - str.replace(durationRE, function (_, n, units) { - // if no units, find next smallest units or fall back to format value (ms) - if (!units) { - if (prevUnits) { - for (var u in parse) if (parse[u] < prevUnits) { units = u; break } - } - else units = format - } - else units = units.toLowerCase() - if (Object.prototype.hasOwnProperty.call(parse, units)) { - units = parse[units] - } else if (Object.prototype.hasOwnProperty.call(parse, units.replace(/s$/, ''))) { - units = parse[units.replace(/s$/, '')] - } else { - units = null - } - if (units) result = (result || 0) + Math.abs(parseFloat(n, 10)) * units, prevUnits = units - }) - - return result && ((result / (parse[format] || 1)) * (str[0] === '-' ? -1 : 1)) -} - -export default parse diff --git a/locale/de.js b/locale/de.js new file mode 100644 index 0000000..b8b0a45 --- /dev/null +++ b/locale/de.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.jahr = unit.j = en.y +unit.monat = en.month +unit.woche = en.w +unit.tag = unit.t = en.d +unit.stunde = en.h +unit.minute = en.m +unit.sekunde = en.s +unit.millisekunde = en.ms +unit.mikrosekunde = en.us +unit.nanosekunde = en.ns + +unit.group = '.' +unit.decimal = ',' + +export default unit diff --git a/locale/en.js b/locale/en.js new file mode 100644 index 0000000..bd373ff --- /dev/null +++ b/locale/en.js @@ -0,0 +1,18 @@ +const unit = Object.create(null) +const m = 60000, h = m * 60, d = h * 24, y = d * 365.25 + +unit.year = unit.yr = unit.y = y +unit.month = unit.b = y / 12 +unit.week = unit.wk = unit.w = d * 7 +unit.day = unit.d = d +unit.hour = unit.hr = unit.h = h +unit.minute = unit.min = unit.m = m +unit.second = unit.sec = unit.s = 1000 +unit.millisecond = unit.millisec = unit.ms = 1 +unit.µs = unit.μs = unit.us = unit.microsecond = 1e-3 +unit.nanosecond = unit.ns = 1e-6 + +unit.group = ',' +unit.decimal = '.' + +export default unit diff --git a/locale/es.js b/locale/es.js new file mode 100644 index 0000000..1af9be9 --- /dev/null +++ b/locale/es.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.año = unit.a = en.y +unit.mes = unit.b = en.month +unit.semana = en.w +unit.día = en.d +unit.hora = en.h +unit.minuto = en.m +unit.segundo = en.s +unit.milisegundo = en.ms +unit.microsegundo = en.us +unit.nanosegundo = en.ns + +unit.group = '.' +unit.decimal = ',' + +export default unit diff --git a/locale/fr.js b/locale/fr.js new file mode 100644 index 0000000..ade1de2 --- /dev/null +++ b/locale/fr.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.année = unit.an = unit.a = en.y +unit.mois = unit.mo = en.month +unit.semaine = unit.sem = en.w +unit.jour = unit.j = en.d +unit.heure = en.h +unit.minute = en.m +unit.seconde = en.s +unit.milliseconde = en.ms +unit.microseconde = en.us +unit.nanoseconde = en.ns + +unit.group = ' ' +unit.decimal = ',' + +export default unit diff --git a/locale/ja.js b/locale/ja.js new file mode 100644 index 0000000..2d33e53 --- /dev/null +++ b/locale/ja.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.年 = unit.年間 = en.y +unit.月 = unit.ヶ月 = en.month +unit.週 = unit.週間 = en.w +unit.日 = en.d +unit.時間 = unit.時 = en.h +unit.分 = unit.分間 = en.m +unit.秒 = unit.秒間 = en.s +unit.ミリ秒 = en.ms +unit.マイクロ秒 = en.us +unit.ナノ秒 = en.ns + +unit.group = ',' +unit.decimal = '.' + +export default unit diff --git a/locale/pt.js b/locale/pt.js new file mode 100644 index 0000000..3db11e8 --- /dev/null +++ b/locale/pt.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.ano = unit.a = en.y +unit.mês = unit.mes = en.month +unit.semana = unit.sem = en.w +unit.dia = en.d +unit.hora = en.h +unit.minuto = en.m +unit.segundo = unit.seg = en.s +unit.milissegundo = en.ms +unit.microssegundo = en.us +unit.nanossegundo = en.ns + +unit.group = '.' +unit.decimal = ',' + +export default unit diff --git a/locale/ru.js b/locale/ru.js new file mode 100644 index 0000000..edaa012 --- /dev/null +++ b/locale/ru.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.год = unit.г = en.y +unit.месяц = unit.мес = en.month +unit.неделя = unit.нед = en.w +unit.день = unit.д = en.d +unit.час = unit.ч = en.h +unit.минута = unit.мин = en.m +unit.секунда = unit.сек = en.s +unit.миллисекунда = unit.мс = en.ms +unit.микросекунда = unit.мкс = en.us +unit.наносекунда = unit.нс = en.ns + +unit.group = ' ' +unit.decimal = ',' + +export default unit diff --git a/locale/zh.js b/locale/zh.js new file mode 100644 index 0000000..395ad5a --- /dev/null +++ b/locale/zh.js @@ -0,0 +1,19 @@ +import en from './en.js' + +const unit = Object.create(en) + +unit.年 = en.y +unit.月 = en.month +unit.周 = unit.星期 = en.w +unit.天 = unit.日 = en.d +unit.小时 = unit.时 = en.h +unit.分钟 = unit.分 = en.m +unit.秒 = unit.秒钟 = en.s +unit.毫秒 = en.ms +unit.微秒 = en.us +unit.纳秒 = en.ns + +unit.group = ',' +unit.decimal = '.' + +export default unit diff --git a/package-lock.json b/package-lock.json index d614017..fc6a0e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "parse-duration", - "version": "1.1.2", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "parse-duration", - "version": "1.1.2", + "version": "2.0.0", "license": "MIT", "devDependencies": { "tape": "^4.8.0" diff --git a/package.json b/package.json index fc49dbf..a39297e 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,16 @@ { "name": "parse-duration", - "version": "1.1.2", - "description": "convert a human readable duration string to a duration format", + "version": "2.0.0", + "description": "Convert a human readable duration string to a duration format", "keywords": [ "parse", "duration", "time" ], - "module": "./index.mjs", + "module": "./index.js", "main": "./index.js", "types": "./index.d.ts", - "exports": { - "import": "./index.mjs", - "default": "./index.js" - }, + "type": "module", "dependencies": {}, "devDependencies": { "tape": "^4.8.0" @@ -24,12 +21,14 @@ "repository": "git://github.com/jkroso/parse-duration.git", "bugs": "https://github.com/jkroso/parse-duration/issues", "author": "Jake Rosoman", + "contributors": [ + "Jake Rosoman", + "Dmitry Iv