Compare commits

..

13 Commits

Author SHA1 Message Date
cupcakearmy c9514fa0aa 1.1.2 2024-07-29 15:12:17 +02:00
cupcakearmy d913a35ae9 update deps 2024-07-29 15:12:11 +02:00
cupcakearmy 99d35a9ade readme 2024-03-04 11:36:29 +01:00
cupcakearmy 8679a04346 update deps 2024-03-04 11:25:17 +01:00
cupcakearmy ec25164cba testing 2022-07-16 17:34:20 +02:00
cupcakearmy 90fd28ef95 Merge branch 'master' of https://github.com/CupCakeArmy/uhrwerk 2022-07-16 17:29:27 +02:00
cupcakearmy 270b27d905 update deps and add esm support 2022-07-16 17:29:22 +02:00
cupcakearmy 750ad01d72 Update README.md 2021-03-15 18:46:33 +01:00
cupcakearmy fc5b828270 Update README.md 2020-09-19 12:00:26 +02:00
cupcakearmy 72d460e41f Merge branch 'master' of https://github.com/CupCakeArmy/uhrwerk 2020-05-26 10:38:33 +02:00
cupcakearmy c8231c3818 funding 2020-05-26 10:38:30 +02:00
cupcakearmy 1a7d00f9c9 Update README.md 2020-03-20 11:24:25 +01:00
cupcakearmy e3e93d5083 Merge pull request #1 from cupcakearmy/add-license-1
Create LICENSE
2020-03-20 11:23:13 +01:00
10 changed files with 1900 additions and 261 deletions
+1
View File
@@ -0,0 +1 @@
github: cupcakearmy
+1 -4
View File
@@ -1,5 +1,2 @@
node_modules
yarn.lock
lib
.idea
dist
-3
View File
@@ -1,3 +0,0 @@
*
!lib/index.js
!lib/index.d.ts
+23 -19
View File
@@ -1,27 +1,31 @@
# uhrwerk 🕰
![package size](https://img.shields.io/bundlephobia/min/uhrwerk?style=flat)
![downloads badge](https://img.shields.io/npm/dt/uhrwerk)
![types badge](https://img.shields.io/npm/types/uhrwerk)
![version badge](https://img.shields.io/npm/v/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')
+27 -13
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+121 -125
View File
@@ -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
View File
@@ -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
View 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`)
})
})
})
+3 -16
View File
@@ -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
}
}