mirror of
https://github.com/cupcakearmy/uhrwerk.git
synced 2025-09-07 11:10:45 +00:00
Compare commits
13 Commits
add-licens
...
c9514fa0aa
Author | SHA1 | Date | |
---|---|---|---|
c9514fa0aa | |||
d913a35ae9 | |||
99d35a9ade | |||
8679a04346 | |||
ec25164cba | |||
90fd28ef95 | |||
270b27d905 | |||
750ad01d72 | |||
fc5b828270 | |||
72d460e41f | |||
c8231c3818 | |||
1a7d00f9c9 | |||
e3e93d5083 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: cupcakearmy
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,2 @@
|
||||
node_modules
|
||||
yarn.lock
|
||||
lib
|
||||
|
||||
.idea
|
||||
dist
|
||||
|
@@ -1,3 +0,0 @@
|
||||
*
|
||||
!lib/index.js
|
||||
!lib/index.d.ts
|
42
README.md
42
README.md
@@ -1,27 +1,31 @@
|
||||
# uhrwerk 🕰
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
Minimal time duration utility. Replacement for MomentJS Durations. If you are looking into the time component of MomentJS check out this awesome library [dayjs](https://github.com/iamkun/dayjs).
|
||||
|
||||
📦 It's **tiny**: [1.6kB](https://bundlephobia.com/result?p=uhrwerk@1.0.0) vs moment js [231.7kb](https://bundlephobia.com/result?p=moment@latest)
|
||||
📦 It's **tiny**: [2kB](https://bundlephobia.com/package/uhrwerk@latest) vs moment js [295kB](https://bundlephobia.com/result?p=moment@latest)
|
||||
|
||||
**Typescript typings included**
|
||||
🌈 No dependencies, types included.
|
||||
|
||||
## Quickstart 🚀
|
||||
|
||||
```typescript
|
||||
// Whatever import you prefer
|
||||
// const { Duration } = require('uhrwerk')
|
||||
import { Duration } from 'uhrwerk'
|
||||
|
||||
const d = new Duration(10, 'days')
|
||||
d.subtract(1, 'week')
|
||||
d.add(5, 'minutes')
|
||||
|
||||
d.humanize() // '3 days'
|
||||
d.minutes() // 5
|
||||
d.asMinute() // 4325
|
||||
d.humanize() // '3 days'
|
||||
d.minutes() // 5
|
||||
d.asMinute() // 4325
|
||||
|
||||
d.subtract(3, 'days')
|
||||
d.humanize() // 'a few minutes'
|
||||
d.humanize() // 'a few minutes'
|
||||
```
|
||||
|
||||
### Reference 📒
|
||||
@@ -30,13 +34,13 @@ d.humanize() // 'a few minutes'
|
||||
|
||||
- amount: number
|
||||
- interval:
|
||||
- millisecond, milliseconds, ms
|
||||
- second, seconds, s
|
||||
- minute, minutes, m
|
||||
- hour, hours, h
|
||||
- day, days, d
|
||||
- week, weeks, w
|
||||
- year, years, y
|
||||
- millisecond, milliseconds, ms
|
||||
- second, seconds, s
|
||||
- minute, minutes, m
|
||||
- hour, hours, h
|
||||
- day, days, d
|
||||
- week, weeks, w
|
||||
- year, years, y
|
||||
|
||||
###### Examples
|
||||
|
||||
@@ -44,7 +48,7 @@ d.humanize() // 'a few minutes'
|
||||
const a = new Duration(1, 'day')
|
||||
const b = new Duration(2, 'days')
|
||||
const c = new Duration(0.5, 'year')
|
||||
const d = new Duration (Date.now(), 'ms')
|
||||
const d = new Duration(Date.now(), 'ms')
|
||||
```
|
||||
|
||||
#### `.add(amount, interval)`
|
||||
@@ -137,9 +141,9 @@ The order of the array is important. The first match will return, like in a stan
|
||||
|
||||
```javascript
|
||||
const humanizer = [
|
||||
[d => d.days() > 1, d => `${d.days()} days`],
|
||||
[d => d.days() > 0, d => `1 day`],
|
||||
[() => true, () => 'catch all, below 1 day'],
|
||||
[(d) => d.days() > 1, (d) => `${d.days()} days`],
|
||||
[(d) => d.days() > 0, (d) => `1 day`],
|
||||
[() => true, () => 'catch all, below 1 day'],
|
||||
]
|
||||
|
||||
const a = new Duration(2, 'days')
|
||||
|
42
package.json
42
package.json
@@ -1,24 +1,38 @@
|
||||
{
|
||||
"name": "uhrwerk",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.2",
|
||||
"description": "time utility",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "yarn run build && mocha",
|
||||
"prepublishOnly": "npm run test"
|
||||
},
|
||||
"keywords": [
|
||||
"time",
|
||||
"interval",
|
||||
"humand-readable",
|
||||
"human-readable",
|
||||
"utility"
|
||||
],
|
||||
"author": "Niccolo Borgioli",
|
||||
"license": "MIT",
|
||||
"author": "Niccolo Borgioli",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./dist/index.cjs",
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup src/index.ts --format cjs,esm --dts --sourcemap",
|
||||
"prepublishOnly": "pnpm run test",
|
||||
"test": "pnpm run build && mocha"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "6.x",
|
||||
"typescript": "3.x"
|
||||
}
|
||||
}
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"mocha": "^10.7.0",
|
||||
"tsup": "^8.2.3",
|
||||
"typescript": "^5.5.4"
|
||||
},
|
||||
"packageManager": "pnpm@9.6.0"
|
||||
}
|
||||
|
1648
pnpm-lock.yaml
generated
Normal file
1648
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
248
src/index.ts
248
src/index.ts
@@ -1,25 +1,25 @@
|
||||
type Intervals =
|
||||
'millisecond'
|
||||
| 'milliseconds'
|
||||
| 'ms'
|
||||
| 'second'
|
||||
| 'seconds'
|
||||
| 's'
|
||||
| 'minute'
|
||||
| 'minutes'
|
||||
| 'm'
|
||||
| 'hour'
|
||||
| 'hours'
|
||||
| 'h'
|
||||
| 'day'
|
||||
| 'days'
|
||||
| 'd'
|
||||
| 'week'
|
||||
| 'weeks'
|
||||
| 'w'
|
||||
| 'year'
|
||||
| 'years'
|
||||
| 'y'
|
||||
| 'millisecond'
|
||||
| 'milliseconds'
|
||||
| 'ms'
|
||||
| 'second'
|
||||
| 'seconds'
|
||||
| 's'
|
||||
| 'minute'
|
||||
| 'minutes'
|
||||
| 'm'
|
||||
| 'hour'
|
||||
| 'hours'
|
||||
| 'h'
|
||||
| 'day'
|
||||
| 'days'
|
||||
| 'd'
|
||||
| 'week'
|
||||
| 'weeks'
|
||||
| 'w'
|
||||
| 'year'
|
||||
| 'years'
|
||||
| 'y'
|
||||
|
||||
const Millisecond = 1
|
||||
const Second = Millisecond * 1000
|
||||
@@ -34,132 +34,128 @@ export type HumanizerReturnFN = (duration: Duration) => string
|
||||
export type Humanizer = [HumanizerTestFN, HumanizerReturnFN][]
|
||||
|
||||
const defaultHumanizer: Humanizer = [
|
||||
[d => d.years() > 0, d => `${d.years()} years`],
|
||||
[d => d.weeks() > 1, d => `${d.weeks()} weeks`],
|
||||
[d => d.days() > 0, d => `${d.days()} days`],
|
||||
[d => d.hours() > 0, d => `${d.hours()} hours`],
|
||||
[d => d.minutes() > 5, d => `${d.minutes()} minutes`],
|
||||
[d => d.minutes() > 0, _ => `a few minutes`],
|
||||
[() => true, () => `a moment`],
|
||||
[(d) => d.years() > 0, (d) => `${d.years()} years`],
|
||||
[(d) => d.weeks() > 1, (d) => `${d.weeks()} weeks`],
|
||||
[(d) => d.days() > 0, (d) => `${d.days()} days`],
|
||||
[(d) => d.hours() > 0, (d) => `${d.hours()} hours`],
|
||||
[(d) => d.minutes() > 5, (d) => `${d.minutes()} minutes`],
|
||||
[(d) => d.minutes() > 0, (_) => `a few minutes`],
|
||||
[() => true, () => `a moment`],
|
||||
]
|
||||
|
||||
|
||||
export class Duration {
|
||||
private duration: number
|
||||
|
||||
private duration: number
|
||||
constructor(amount: number, interval: Intervals) {
|
||||
this.duration = Duration.ProcessInterval(amount, interval)
|
||||
}
|
||||
|
||||
constructor(amount: number, interval: Intervals) {
|
||||
this.duration = Duration.ProcessInterval(amount, interval)
|
||||
}
|
||||
private static ProcessInterval(amount: number, interval: Intervals): number {
|
||||
switch (interval.toLowerCase()) {
|
||||
case 'millisecond':
|
||||
case 'milliseconds':
|
||||
case 'ms':
|
||||
return amount * Millisecond
|
||||
case 'second':
|
||||
case 'seconds':
|
||||
case 's':
|
||||
return amount * Second
|
||||
case 'minute':
|
||||
case 'minutes':
|
||||
case 'm':
|
||||
return amount * Minute
|
||||
case 'hour':
|
||||
case 'hours':
|
||||
case 'h':
|
||||
return amount * Hour
|
||||
case 'day':
|
||||
case 'days':
|
||||
case 'd':
|
||||
return amount * Day
|
||||
case 'week':
|
||||
case 'weeks':
|
||||
case 'w':
|
||||
return amount * Week
|
||||
case 'year':
|
||||
case 'years':
|
||||
case 'y':
|
||||
return amount * Year
|
||||
default:
|
||||
throw new Error('Wrong interval')
|
||||
}
|
||||
}
|
||||
|
||||
private static ProcessInterval(amount: number, interval: Intervals): number {
|
||||
switch (interval.toLowerCase()) {
|
||||
case 'millisecond':
|
||||
case 'milliseconds':
|
||||
case 'ms':
|
||||
return amount * Millisecond
|
||||
case 'second':
|
||||
case 'seconds':
|
||||
case 's':
|
||||
return amount * Second
|
||||
case 'minute':
|
||||
case 'minutes':
|
||||
case 'm':
|
||||
return amount * Minute
|
||||
case 'hour':
|
||||
case 'hours':
|
||||
case 'h':
|
||||
return amount * Hour
|
||||
case 'day':
|
||||
case 'days':
|
||||
case 'd':
|
||||
return amount * Day
|
||||
case 'week':
|
||||
case 'weeks':
|
||||
case 'w':
|
||||
return amount * Week
|
||||
case 'year':
|
||||
case 'years':
|
||||
case 'y':
|
||||
return amount * Year
|
||||
default:
|
||||
throw new Error('Wrong interval')
|
||||
}
|
||||
}
|
||||
public add(amount: number, interval: Intervals): Duration {
|
||||
this.duration += Duration.ProcessInterval(amount, interval)
|
||||
return this
|
||||
}
|
||||
|
||||
public add(amount: number, interval: Intervals): Duration {
|
||||
this.duration += Duration.ProcessInterval(amount, interval)
|
||||
return this
|
||||
}
|
||||
public subtract(amount: number, interval: Intervals): Duration {
|
||||
this.duration -= Duration.ProcessInterval(amount, interval)
|
||||
return this
|
||||
}
|
||||
|
||||
public subtract(amount: number, interval: Intervals): Duration {
|
||||
this.duration -= Duration.ProcessInterval(amount, interval)
|
||||
return this
|
||||
}
|
||||
public asMilliseconds(): number {
|
||||
return this.duration
|
||||
}
|
||||
|
||||
public asMilliseconds(): number {
|
||||
return this.duration
|
||||
}
|
||||
public asSeconds(): number {
|
||||
return this.duration / Second
|
||||
}
|
||||
|
||||
public asSeconds(): number {
|
||||
return this.duration / Second
|
||||
}
|
||||
public asMinutes(): number {
|
||||
return this.duration / Minute
|
||||
}
|
||||
|
||||
public asMinutes(): number {
|
||||
return this.duration / Minute
|
||||
}
|
||||
public asHours(): number {
|
||||
return this.duration / Hour
|
||||
}
|
||||
|
||||
public asHours(): number {
|
||||
return this.duration / Hour
|
||||
}
|
||||
public asDays(): number {
|
||||
return this.duration / Day
|
||||
}
|
||||
|
||||
public asDays(): number {
|
||||
return this.duration / Day
|
||||
}
|
||||
public asWeeks(): number {
|
||||
return this.duration / Week
|
||||
}
|
||||
|
||||
public asWeeks(): number {
|
||||
return this.duration / Week
|
||||
}
|
||||
public asYears(): number {
|
||||
return this.duration / Year
|
||||
}
|
||||
|
||||
public asYears(): number {
|
||||
return this.duration / Year
|
||||
}
|
||||
public milliseconds(): number {
|
||||
return ((((((this.duration % Year) % Day) % Hour) % Minute) % Second) / Millisecond) | 0
|
||||
}
|
||||
|
||||
public milliseconds(): number {
|
||||
return (this.duration % Year % Day % Hour % Minute % Second) / Millisecond | 0
|
||||
}
|
||||
public seconds(): number {
|
||||
return (((((this.duration % Year) % Day) % Hour) % Minute) / Second) | 0
|
||||
}
|
||||
|
||||
public seconds(): number {
|
||||
return (this.duration % Year % Day % Hour % Minute) / Second | 0
|
||||
}
|
||||
public minutes(): number {
|
||||
return ((((this.duration % Year) % Day) % Hour) / Minute) | 0
|
||||
}
|
||||
|
||||
public minutes(): number {
|
||||
return (this.duration % Year % Day % Hour) / Minute | 0
|
||||
}
|
||||
public hours(): number {
|
||||
return (((this.duration % Year) % Day) / Hour) | 0
|
||||
}
|
||||
|
||||
public hours(): number {
|
||||
return (this.duration % Year % Day) / Hour | 0
|
||||
}
|
||||
public days(): number {
|
||||
return ((this.duration % Year) / Day) | 0
|
||||
}
|
||||
|
||||
public days(): number {
|
||||
return (this.duration % Year) / Day | 0
|
||||
}
|
||||
public weeks(): number {
|
||||
return (this.duration / Week) | 0
|
||||
}
|
||||
|
||||
public weeks(): number {
|
||||
return (this.duration) / Week | 0
|
||||
}
|
||||
public years(): number {
|
||||
return (this.duration / Year) | 0
|
||||
}
|
||||
|
||||
public years(): number {
|
||||
return (this.duration) / Year | 0
|
||||
}
|
||||
public humanize(humanizer?: Humanizer): string {
|
||||
if (!humanizer) humanizer = defaultHumanizer
|
||||
|
||||
public humanize(humanizer?: Humanizer): string {
|
||||
if (!humanizer) humanizer = defaultHumanizer
|
||||
for (const [control, value] of humanizer) if (control(this)) return value(this)
|
||||
|
||||
for (const [control, value] of humanizer)
|
||||
if (control(this))
|
||||
return value(this)
|
||||
|
||||
return ''
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
78
test/main.js
78
test/main.js
@@ -1,78 +0,0 @@
|
||||
const { describe, it } = require('mocha')
|
||||
const a = require('assert')
|
||||
|
||||
const { Duration } = require('../')
|
||||
|
||||
describe('Duration', () => {
|
||||
|
||||
describe('Basics', () => {
|
||||
|
||||
it('as unit', () => {
|
||||
const d = new Duration(.5, 'year')
|
||||
|
||||
a.strictEqual(d.asMilliseconds(), 1000 * 60 * 60 * 24 * 365.25 / 2)
|
||||
a.strictEqual(d.asSeconds(), 60 * 60 * 24 * 365.25 / 2)
|
||||
a.strictEqual(d.asMinutes(), 60 * 24 * 365.25 / 2)
|
||||
a.strictEqual(d.asHours(), 24 * 365.25 / 2)
|
||||
a.strictEqual(d.asDays(), 365.25 / 2)
|
||||
a.strictEqual(d.asWeeks(), 365.25 / 7 / 2)
|
||||
a.strictEqual(d.asYears(), .5)
|
||||
})
|
||||
|
||||
it('add / subtract', () => {
|
||||
const d = new Duration(1, 'day')
|
||||
d.add(4, 'hours')
|
||||
a.strictEqual(d.asHours(), 28)
|
||||
d.subtract(.5, 'day')
|
||||
a.strictEqual(d.asHours(), 16)
|
||||
})
|
||||
|
||||
it('exact units', () => {
|
||||
const d = new Duration(1, 'day')
|
||||
|
||||
d.add(42, 'milliseconds')
|
||||
a.strictEqual(d.milliseconds(), 42)
|
||||
|
||||
d.add(5, 'seconds')
|
||||
a.strictEqual(d.seconds(), 5)
|
||||
|
||||
d.add(27, 'minutes')
|
||||
a.strictEqual(d.minutes(), 27)
|
||||
|
||||
d.add(8, 'hours')
|
||||
a.strictEqual(d.hours(), 8)
|
||||
|
||||
d.add(3, 'days')
|
||||
a.strictEqual(d.days(), 4)
|
||||
|
||||
d.add(17, 'weeks')
|
||||
a.strictEqual(d.weeks(), 17)
|
||||
|
||||
d.add(2, 'years')
|
||||
a.strictEqual(d.years(), 2)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('Humanize', () => {
|
||||
|
||||
it('few minutes', () => {
|
||||
a.strictEqual(new Duration(2, 'minutes').humanize(), 'a few minutes')
|
||||
a.strictEqual(new Duration(16, 'minutes').humanize(), '16 minutes')
|
||||
a.strictEqual(new Duration(30, 'seconds').humanize(), 'a moment')
|
||||
})
|
||||
|
||||
it('custom humanizer', () => {
|
||||
const humanizer = [
|
||||
[d => d.days() > 0, d => `yus for ${d.days()}`],
|
||||
[() => true, () => 'cool'],
|
||||
]
|
||||
|
||||
const d = new Duration(5, 'minutes')
|
||||
a.strictEqual(d.humanize(humanizer), 'cool')
|
||||
d.add(2, 'days')
|
||||
a.strictEqual(d.humanize(humanizer), `yus for 2`)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
73
test/main.mjs
Normal file
73
test/main.mjs
Normal file
@@ -0,0 +1,73 @@
|
||||
import { strictEqual } from 'assert'
|
||||
import { describe, it } from 'mocha'
|
||||
|
||||
import { Duration } from '../dist/index.js'
|
||||
|
||||
describe('Duration', () => {
|
||||
describe('Basics', () => {
|
||||
it('as unit', () => {
|
||||
const d = new Duration(0.5, 'year')
|
||||
|
||||
strictEqual(d.asMilliseconds(), (1000 * 60 * 60 * 24 * 365.25) / 2)
|
||||
strictEqual(d.asSeconds(), (60 * 60 * 24 * 365.25) / 2)
|
||||
strictEqual(d.asMinutes(), (60 * 24 * 365.25) / 2)
|
||||
strictEqual(d.asHours(), (24 * 365.25) / 2)
|
||||
strictEqual(d.asDays(), 365.25 / 2)
|
||||
strictEqual(d.asWeeks(), 365.25 / 7 / 2)
|
||||
strictEqual(d.asYears(), 0.5)
|
||||
})
|
||||
|
||||
it('add / subtract', () => {
|
||||
const d = new Duration(1, 'day')
|
||||
d.add(4, 'hours')
|
||||
strictEqual(d.asHours(), 28)
|
||||
d.subtract(0.5, 'day')
|
||||
strictEqual(d.asHours(), 16)
|
||||
})
|
||||
|
||||
it('exact units', () => {
|
||||
const d = new Duration(1, 'day')
|
||||
|
||||
d.add(42, 'milliseconds')
|
||||
strictEqual(d.milliseconds(), 42)
|
||||
|
||||
d.add(5, 'seconds')
|
||||
strictEqual(d.seconds(), 5)
|
||||
|
||||
d.add(27, 'minutes')
|
||||
strictEqual(d.minutes(), 27)
|
||||
|
||||
d.add(8, 'hours')
|
||||
strictEqual(d.hours(), 8)
|
||||
|
||||
d.add(3, 'days')
|
||||
strictEqual(d.days(), 4)
|
||||
|
||||
d.add(17, 'weeks')
|
||||
strictEqual(d.weeks(), 17)
|
||||
|
||||
d.add(2, 'years')
|
||||
strictEqual(d.years(), 2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Humanize', () => {
|
||||
it('few minutes', () => {
|
||||
strictEqual(new Duration(2, 'minutes').humanize(), 'a few minutes')
|
||||
strictEqual(new Duration(16, 'minutes').humanize(), '16 minutes')
|
||||
strictEqual(new Duration(30, 'seconds').humanize(), 'a moment')
|
||||
})
|
||||
|
||||
it('custom humanizer', () => {
|
||||
const humanizer = [
|
||||
[(d) => d.days() > 0, (d) => `yus for ${d.days()}`],
|
||||
[() => true, () => 'cool'],
|
||||
]
|
||||
|
||||
const d = new Duration(5, 'minutes')
|
||||
strictEqual(d.humanize(humanizer), 'cool')
|
||||
d.add(2, 'days')
|
||||
strictEqual(d.humanize(humanizer), `yus for 2`)
|
||||
})
|
||||
})
|
||||
})
|
@@ -1,23 +1,10 @@
|
||||
{
|
||||
"extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "commonjs",
|
||||
"target": "es2022",
|
||||
"module": "es2022",
|
||||
"declaration": true,
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictBindCallApply": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user