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.
Files changed (3) hide show
  1. package/README.md +61 -60
  2. package/index.js +2 -0
  3. package/package.json +12 -4
package/README.md CHANGED
@@ -1,102 +1,103 @@
1
1
  # daymath
2
2
 
3
- Calendar date math for **ISO 8601** day strings. **date-fns-shaped** names. **Temporal.PlainDate** under the hood.
3
+ [![npm](https://img.shields.io/npm/v/daymath.svg)](https://www.npmjs.com/package/daymath)
4
+ [![ci](https://github.com/leemr/daymath/actions/workflows/ci.yml/badge.svg)](https://github.com/leemr/daymath/actions/workflows/ci.yml)
5
+ [![codecov](https://codecov.io/gh/leemr/daymath/graph/badge.svg)](https://codecov.io/gh/leemr/daymath)
6
+ [![license](https://img.shields.io/npm/l/daymath.svg)](./LICENSE)
7
+ [![node](https://img.shields.io/node/v/daymath.svg)](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
- ## Why
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
- `Date` is a timestamp. Calendar work (“add one month”, “days between hire and start”) is not. This package only does plain calendar days.
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
- ## Usage
27
+ Most people should keep using **`daymath` on npmjs**.
16
28
 
17
29
  ```js
18
- import {
19
- addDays,
20
- addMonths,
21
- differenceInDays,
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
- isBefore('2026-08-05', '2026-08-06') // true
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
- **Inputs:** ISO 8601 day string or `Temporal.PlainDate`.
42
- - `YYYY-MM-DD` (years 0000–9999)
43
- - expanded `±YYYYYY-MM-DD` (e.g. `+010000-01-01`)
38
+ ```bash
39
+ node examples/basic.mjs # from a clone
40
+ ```
44
41
 
45
- **Outputs:** Temporal’s ISO day string (same forms).
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
- `Date` throws (including `isValid(date)`). Bad strings: math helpers throw; `isValid('asdf')` → `false`. Time-bearing / sloppy forms throw.
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
- See [FUTURE.md](./FUTURE.md) for backlog (bundle size, business days, …).
51
+ `Date` **throws** (including `isValid`). `isValid('asdf')` `false`.
50
52
 
51
- ## date-fns parity notes
53
+ ## date-fns parity (names, not `Date`)
52
54
 
53
55
  | Topic | daymath |
54
56
  |-------|---------|
55
- | Value type | ISO day string (not `Date`) |
56
- | `isSameDay` | Alias of `isEqual` (same calendar day) |
57
- | `isValid` | Our predicate: valid day string / PlainDate. `Date` **throws** (not date-fns’s Date check) |
58
- | `getMonth` / `setMonth` | **0–11** like Date/date-fns (0 = January) |
59
- | `getDay` | **0–6** like Date/date-fns (0 = Sunday) |
60
- | `weekStartsOn` | `0` = Sunday … `6` = Saturday (default `0`) |
61
- | Intervals | `{ start, end }` inclusive for `each*` / `isWithin` / `clamp` |
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 (0.2)
65
+ ## API
65
66
 
66
- ### Parse / format
67
- `parse` · `format` · `isValid`
67
+ **Parse** `parse` · `format` · `isValid`
68
68
 
69
- ### Add / sub
70
- `addDays` / `subDays` · `addWeeks` / `subWeeks` · `addMonths` / `subMonths` · `addYears` / `subYears` · `addQuarters` / `subQuarters`
69
+ **Add/sub** — Days · Weeks · Months · Years · Quarters
71
70
 
72
- ### Get / set
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
- ### Start / end
77
- `startOfMonth` / `endOfMonth` · `startOfYear` / `endOfYear` · `startOfQuarter` / `endOfQuarter` · `startOfWeek` / `endOfWeek`
73
+ **Bounds** `startOf`/`endOf` Month · Year · Quarter · Week
78
74
 
79
- ### Differences
80
- `differenceInDays` · `differenceInWeeks` · `differenceInMonths` · `differenceInCalendarMonths` · `differenceInYears` · `differenceInCalendarYears` · `differenceInQuarters` · `differenceInCalendarQuarters`
75
+ **Diffs** — Days · Weeks · Months · CalendarMonths · Years · CalendarYears · Quarters · CalendarQuarters
81
76
 
82
- ### Compare
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
- ### Weekday / month edges
86
- `isSunday`…`isSaturday` · `isWeekend` · `isFirstDayOfMonth` · `isLastDayOfMonth`
79
+ **Weekday** — `isSunday`…`isSaturday` · `isWeekend` · first/last day of month
87
80
 
88
- ### Intervals
89
- `eachDayOfInterval` · `eachMonthOfInterval` · `eachYearOfInterval` · `isWithinInterval` · `clamp` · `areIntervalsOverlapping`
81
+ **Intervals** — `eachDayOfInterval` · `eachMonthOfInterval` · `eachYearOfInterval` · `isWithinInterval` · `clamp` · `areIntervalsOverlapping`
90
82
 
91
- Amounts must be finite integers.
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
- Ships `index.d.ts` (no TypeScript compile step). Source is plain JS.
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.1",
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
- "prepublishOnly": "npm test"
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.com/leemr/daymath#readme",
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
  }