nl2time 0.3.1 → 0.3.2

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 CHANGED
@@ -120,11 +120,11 @@ Every imported conformance case carries machine-readable provenance (upstream pr
120
120
  pip install nl2time
121
121
  ```
122
122
 
123
- The Python engine port lives in [`python/`](python/) (`whenever`-based time model): IR validation, `TimeContext`, and the full deterministic resolver at **100% bit-exact parity** with the JS reference across all 2,760 engine-parity fixtures (`corpus/ir/`), enforced in CI on every push. Parsers and `describe()` are JS-only so far — [docs/porting.md](docs/porting.md) has the strategy and the divergence gates.
123
+ The Python engine port lives in [`python/`](python/) (`whenever`-based time model): IR validation, `TimeContext`, and the full deterministic resolver at **100% bit-exact parity** with the JS reference across all 2,782 engine-parity fixtures (`corpus/ir/`), enforced in CI on every push. Parsers and `describe()` are JS-only so far — [docs/porting.md](docs/porting.md) has the strategy and the divergence gates.
124
124
 
125
125
  ## Release history
126
126
 
127
- See **[CHANGELOG.md](CHANGELOG.md)** and [GitHub releases](https://github.com/AndyFooBlah/nl2time/releases). Current: v0.3.0 (JS, multilingual parsing) · py-v0.1.0 (Python engine). Releases publish to npm/PyPI automatically via OIDC trusted publishing — see [docs/RELEASING.md](docs/RELEASING.md).
127
+ See **[CHANGELOG.md](CHANGELOG.md)** and [GitHub releases](https://github.com/AndyFooBlah/nl2time/releases). Current: v0.3.2 (JS) · py-v0.1.2 (Python engine). Releases publish to npm/PyPI automatically via OIDC trusted publishing — see [docs/RELEASING.md](docs/RELEASING.md).
128
128
 
129
129
  ## Development
130
130
 
@@ -179,7 +179,12 @@ function evalExprInner(expr, ctx, anchor) {
179
179
  if (e.type !== 'interval')
180
180
  continue;
181
181
  const isPoint = Temporal_compare(e.zi.start, e.zi.end) === 0;
182
- const timeGrained = GRAIN_ORDER.indexOf(e.zi.grain) < GRAIN_ORDER.indexOf('day');
182
+ // Clock-time semantics need a fine grain AND a sub-day extent: a
183
+ // multi-day interval whose edges are snap points ("end of year" =
184
+ // Jul 1 → Jan 1) carries grain 'instant' but is a calendar period,
185
+ // not a time of day.
186
+ const timeGrained = GRAIN_ORDER.indexOf(e.zi.grain) < GRAIN_ORDER.indexOf('day') &&
187
+ (isPoint || Temporal_compare(e.zi.start.add({ days: 1 }), e.zi.end) > 0);
183
188
  // Day-grain-or-coarser ends are conversationally inclusive:
184
189
  // "between July 4th and July 10th" covers the 10th. Emit the
185
190
  // inclusive reading (end operand contributes its END) first, with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nl2time",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Bidirectional natural language \u21c4 date/time: parse expressions like 'last week' into concrete intervals, and describe instants as '9pm last night' \u2014 deterministic core, optional LLM assist.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,7 +32,8 @@
32
32
  "typecheck": "tsc --noEmit",
33
33
  "import:recognizers": "node scripts/import-recognizers.mjs",
34
34
  "baselines": "npm run build && node scripts/update-baselines.mjs",
35
- "eval": "npm run build && node scripts/eval.mjs"
35
+ "eval": "npm run build && node scripts/eval.mjs",
36
+ "fixtures": "npm run build && node scripts/generate-ir-fixtures.mjs"
36
37
  },
37
38
  "keywords": [
38
39
  "date",
@@ -55,6 +56,6 @@
55
56
  "vitest": "^3.0.0"
56
57
  },
57
58
  "engines": {
58
- "node": ">=20"
59
+ "node": ">=22"
59
60
  }
60
61
  }