daymath 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -60
- package/index.js +2 -0
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -1,102 +1,103 @@
|
|
|
1
1
|
# daymath
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/daymath)
|
|
4
|
+
[](https://github.com/leemr/daymath/actions/workflows/ci.yml)
|
|
5
|
+
[](https://codecov.io/gh/leemr/daymath)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/daymath)
|
|
8
|
+
|
|
9
|
+
**ISO 8601** calendar day math. **date-fns-shaped** names. **Temporal.PlainDate** under the hood.
|
|
4
10
|
|
|
5
11
|
No `Date`. No time zones. No silent “local now.”
|
|
6
12
|
|
|
13
|
+
[**Play →**](https://leemr.github.io/daymath/) · [npm](https://www.npmjs.com/package/daymath) · [Changelog](./CHANGELOG.md) · [Contributing](./CONTRIBUTING.md) · [FUTURE](./FUTURE.md)
|
|
14
|
+
|
|
7
15
|
```bash
|
|
8
16
|
npm install daymath
|
|
9
17
|
```
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
Same code also publishes to **GitHub Packages** as `@leemr/daymath` (scoped; see [GitHub npm registry docs](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry)):
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
```bash
|
|
22
|
+
# one-time: map the scope (auth with a PAT that has read:packages, or GITHUB_TOKEN in Actions)
|
|
23
|
+
echo '@leemr:registry=https://npm.pkg.github.com' >> .npmrc
|
|
24
|
+
npm install @leemr/daymath
|
|
25
|
+
```
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
Most people should keep using **`daymath` on npmjs**.
|
|
16
28
|
|
|
17
29
|
```js
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
isBefore,
|
|
23
|
-
isSameDay,
|
|
24
|
-
startOfMonth,
|
|
25
|
-
eachDayOfInterval,
|
|
26
|
-
} from 'daymath'
|
|
27
|
-
|
|
28
|
-
addDays('2026-08-06', 1) // '2026-08-07'
|
|
29
|
-
addMonths('2026-01-31', 1) // '2026-02-28' (constrain)
|
|
30
|
+
import { addDays, addMonths, differenceInDays, isSameDay } from 'daymath'
|
|
31
|
+
|
|
32
|
+
addDays('2026-08-06', 1) // '2026-08-07'
|
|
33
|
+
addMonths('2026-01-31', 1) // '2026-02-28'
|
|
30
34
|
differenceInDays('2026-08-06', '2026-08-01') // 5
|
|
31
|
-
|
|
32
|
-
isSameDay('2026-08-06', '2026-08-06') // true (alias of isEqual)
|
|
33
|
-
startOfMonth('2026-08-06') // '2026-08-01'
|
|
34
|
-
addDays('9999-12-31', 1) // '+010000-01-01' (expanded year)
|
|
35
|
-
eachDayOfInterval({
|
|
36
|
-
start: '2026-08-05',
|
|
37
|
-
end: '2026-08-07',
|
|
38
|
-
}) // ['2026-08-05', '2026-08-06', '2026-08-07']
|
|
35
|
+
isSameDay('2026-08-06', '2026-08-06') // true
|
|
39
36
|
```
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
```bash
|
|
39
|
+
node examples/basic.mjs # from a clone
|
|
40
|
+
```
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
## Why
|
|
43
|
+
|
|
44
|
+
`Date` is a timestamp. Hire dates, passport expiry, trip days are **calendar** values. daymath only does plain days as ISO strings.
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
| In | Out |
|
|
47
|
+
|----|-----|
|
|
48
|
+
| `YYYY-MM-DD` or expanded `±YYYYYY-MM-DD` | same forms (Temporal `toString`) |
|
|
49
|
+
| or `Temporal.PlainDate` | string |
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
`Date` **throws** (including `isValid`). `isValid('asdf')` → `false`.
|
|
50
52
|
|
|
51
|
-
## date-fns parity
|
|
53
|
+
## date-fns parity (names, not `Date`)
|
|
52
54
|
|
|
53
55
|
| Topic | daymath |
|
|
54
56
|
|-------|---------|
|
|
55
|
-
|
|
|
56
|
-
| `isSameDay` | Alias of `isEqual`
|
|
57
|
-
| `isValid` |
|
|
58
|
-
| `getMonth` / `setMonth` | **0–11**
|
|
59
|
-
| `getDay` | **0–6**
|
|
60
|
-
| `weekStartsOn` | `0`
|
|
61
|
-
| Intervals | `{ start, end }`
|
|
62
|
-
| `areIntervalsOverlapping` | Default `{ inclusive: false }` (date-fns); pass `true` for closed |
|
|
57
|
+
| Values | ISO day **strings**, not `Date` |
|
|
58
|
+
| `isSameDay` | Alias of `isEqual` |
|
|
59
|
+
| `isValid` | Valid daymath day; **`Date` throws** |
|
|
60
|
+
| `getMonth` / `setMonth` | **0–11** (0 = January) |
|
|
61
|
+
| `getDay` | **0–6** (0 = Sunday) |
|
|
62
|
+
| `weekStartsOn` | default `0` (Sunday) |
|
|
63
|
+
| Intervals | `{ start, end }` |
|
|
63
64
|
|
|
64
|
-
## API
|
|
65
|
+
## API
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
`parse` · `format` · `isValid`
|
|
67
|
+
**Parse** — `parse` · `format` · `isValid`
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
`addDays` / `subDays` · `addWeeks` / `subWeeks` · `addMonths` / `subMonths` · `addYears` / `subYears` · `addQuarters` / `subQuarters`
|
|
69
|
+
**Add/sub** — Days · Weeks · Months · Years · Quarters
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
`getYear` · `getMonth` · `getDate` · `getDay` · `getDayOfYear` · `getDaysInMonth` · `getQuarter` · `isLeapYear`
|
|
74
|
-
`setYear` · `setMonth` · `setDate`
|
|
71
|
+
**Get/set** — `getYear` · `getMonth` · `getDate` · `getDay` · `getDayOfYear` · `getDaysInMonth` · `getQuarter` · `isLeapYear` · `setYear` · `setMonth` · `setDate`
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
`startOfMonth` / `endOfMonth` · `startOfYear` / `endOfYear` · `startOfQuarter` / `endOfQuarter` · `startOfWeek` / `endOfWeek`
|
|
73
|
+
**Bounds** — `startOf`/`endOf` Month · Year · Quarter · Week
|
|
78
74
|
|
|
79
|
-
|
|
80
|
-
`differenceInDays` · `differenceInWeeks` · `differenceInMonths` · `differenceInCalendarMonths` · `differenceInYears` · `differenceInCalendarYears` · `differenceInQuarters` · `differenceInCalendarQuarters`
|
|
75
|
+
**Diffs** — Days · Weeks · Months · CalendarMonths · Years · CalendarYears · Quarters · CalendarQuarters
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
`isBefore` · `isAfter` · `isEqual` · `isSameDay` · `isSameWeek` · `isSameMonth` · `isSameYear` · `isSameQuarter` · `compareAsc` · `compareDesc` · `min` · `max`
|
|
77
|
+
**Compare** — `isBefore` · `isAfter` · `isEqual` · `isSameDay` · `isSameWeek` · Month · Year · Quarter · `compareAsc` · `compareDesc` · `min` · `max`
|
|
84
78
|
|
|
85
|
-
|
|
86
|
-
`isSunday`…`isSaturday` · `isWeekend` · `isFirstDayOfMonth` · `isLastDayOfMonth`
|
|
79
|
+
**Weekday** — `isSunday`…`isSaturday` · `isWeekend` · first/last day of month
|
|
87
80
|
|
|
88
|
-
|
|
89
|
-
`eachDayOfInterval` · `eachMonthOfInterval` · `eachYearOfInterval` · `isWithinInterval` · `clamp` · `areIntervalsOverlapping`
|
|
81
|
+
**Intervals** — `eachDayOfInterval` · `eachMonthOfInterval` · `eachYearOfInterval` · `isWithinInterval` · `clamp` · `areIntervalsOverlapping`
|
|
90
82
|
|
|
91
|
-
Amounts
|
|
83
|
+
Amounts are finite integers.
|
|
92
84
|
|
|
93
85
|
## Temporal
|
|
94
86
|
|
|
95
87
|
Uses global `Temporal` when present; otherwise [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill).
|
|
96
88
|
|
|
97
|
-
## Types
|
|
89
|
+
## Types & tests
|
|
90
|
+
|
|
91
|
+
Plain JS + `index.d.ts` (no compile step). CI runs on Node 18, 20, and 22.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm test
|
|
95
|
+
npm run test:coverage # c8: 100% lines/funcs/branches on index.js + lcov
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
CI uploads coverage to [Codecov](https://codecov.io/gh/leemr/daymath) (see [CONTRIBUTING.md](./CONTRIBUTING.md) for one-time app/token setup).
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
PRs welcome via fork — see [CONTRIBUTING.md](./CONTRIBUTING.md). Security reports: [SECURITY.md](./SECURITY.md).
|
|
100
101
|
|
|
101
102
|
## License
|
|
102
103
|
|
package/index.js
CHANGED
|
@@ -116,6 +116,8 @@ function toInterval(interval) {
|
|
|
116
116
|
* True if value is a valid daymath day (ISO day string or PlainDate).
|
|
117
117
|
* Invalid strings → false. `Date` → throws (not a quiet false — swap trap).
|
|
118
118
|
* @param {unknown} value
|
|
119
|
+
* @returns {boolean}
|
|
120
|
+
* @throws {TypeError} If `value` is a `Date`
|
|
119
121
|
*/
|
|
120
122
|
export function isValid(value) {
|
|
121
123
|
if (value instanceof Date) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "daymath",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Calendar date math (ISO 8601 day / PlainDate). date-fns-shaped. No time zones.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
20
|
"test": "node --test test.js",
|
|
21
|
-
"
|
|
21
|
+
"test:coverage": "c8 --include=index.js --check-coverage --lines 100 --functions 100 --branches 100 --reporter=text --reporter=lcov node --test test.js",
|
|
22
|
+
"prepublishOnly": "npm run test:coverage",
|
|
23
|
+
"publish:github": "node scripts/publish-github-packages.mjs"
|
|
22
24
|
},
|
|
23
25
|
"keywords": [
|
|
24
26
|
"date",
|
|
@@ -26,7 +28,9 @@
|
|
|
26
28
|
"plain-date",
|
|
27
29
|
"temporal",
|
|
28
30
|
"date-fns",
|
|
29
|
-
"YYYY-MM-DD"
|
|
31
|
+
"YYYY-MM-DD",
|
|
32
|
+
"ISO-8601",
|
|
33
|
+
"PlainDate"
|
|
30
34
|
],
|
|
31
35
|
"author": "leemr",
|
|
32
36
|
"license": "MIT",
|
|
@@ -37,11 +41,15 @@
|
|
|
37
41
|
"bugs": {
|
|
38
42
|
"url": "https://github.com/leemr/daymath/issues"
|
|
39
43
|
},
|
|
40
|
-
"homepage": "https://github.
|
|
44
|
+
"homepage": "https://leemr.github.io/daymath/",
|
|
45
|
+
"sideEffects": false,
|
|
41
46
|
"dependencies": {
|
|
42
47
|
"temporal-polyfill": "^1.0.3"
|
|
43
48
|
},
|
|
44
49
|
"engines": {
|
|
45
50
|
"node": ">=18"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"c8": "^12.0.0"
|
|
46
54
|
}
|
|
47
55
|
}
|