@taskade/temporal-parser
Advanced tools
+18
-0
| # @taskade/temporal-parser | ||
| ## 1.2.1 | ||
| ### Patch Changes | ||
| - 3f20258: Add support for ISO 8601 basic format and bare hours in `parseTimeString()` | ||
| **New formats supported:** | ||
| 1. **ISO 8601 basic format** (compact, no colons): | ||
| - `"1430"` → 14:30 | ||
| - `"143045"` → 14:30:45 | ||
| - `"143045.123"` → 14:30:45.123 | ||
| 2. **Bare hours** (defaults to :00 minutes): | ||
| - `"7"` → 7:00 | ||
| - `"7 AM"` → 7:00 AM | ||
| - `"23"` → 23:00 | ||
| The parser intelligently detects the format based on digit count and presence of colons, maintaining full backward compatibility with existing formats. | ||
| ## 1.2.0 | ||
@@ -4,0 +22,0 @@ |
+41
-18
@@ -703,23 +703,20 @@ "use strict"; | ||
| const hourTok = eat("Number" /* Number */); | ||
| let hour = toInt(hourTok.value, "hour", i); | ||
| eat("Colon" /* Colon */); | ||
| const minuteTok = eat("Number" /* Number */); | ||
| const minute = toInt(minuteTok.value, "minute", i); | ||
| if (minuteTok.value.length !== 2) { | ||
| throw new ParseError( | ||
| `Invalid time format: "${trimmed}". Minutes must be 2 digits (e.g., "9:07" not "9:7")`, | ||
| i | ||
| ); | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| let hour; | ||
| let minute = 0; | ||
| let second; | ||
| let fraction; | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const secondTok = eat("Number" /* Number */); | ||
| second = toInt(secondTok.value, "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| const numLen = hourTok.value.length; | ||
| if (!at("Colon" /* Colon */) && (numLen === 4 || numLen === 6)) { | ||
| const timeStr = hourTok.value; | ||
| hour = toInt(timeStr.substring(0, 2), "hour", i); | ||
| minute = toInt(timeStr.substring(2, 4), "minute", i); | ||
| if (numLen === 6) { | ||
| second = toInt(timeStr.substring(4, 6), "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| } | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Dot" /* Dot */) || tryEat("Comma" /* Comma */)) { | ||
@@ -729,2 +726,28 @@ const fracTok = eat("Number" /* Number */); | ||
| } | ||
| } else { | ||
| hour = toInt(hourTok.value, "hour", i); | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const minuteTok = eat("Number" /* Number */); | ||
| minute = toInt(minuteTok.value, "minute", i); | ||
| if (minuteTok.value.length !== 2) { | ||
| throw new ParseError( | ||
| `Invalid time format: "${trimmed}". Minutes must be 2 digits (e.g., "9:07" not "9:7")`, | ||
| i | ||
| ); | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const secondTok = eat("Number" /* Number */); | ||
| second = toInt(secondTok.value, "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Dot" /* Dot */) || tryEat("Comma" /* Comma */)) { | ||
| const fracTok = eat("Number" /* Number */); | ||
| fraction = fracTok.value; | ||
| } | ||
| } | ||
| } | ||
| } | ||
@@ -731,0 +754,0 @@ let ampmStr; |
+41
-18
@@ -660,23 +660,20 @@ // src/lexer-types.ts | ||
| const hourTok = eat("Number" /* Number */); | ||
| let hour = toInt(hourTok.value, "hour", i); | ||
| eat("Colon" /* Colon */); | ||
| const minuteTok = eat("Number" /* Number */); | ||
| const minute = toInt(minuteTok.value, "minute", i); | ||
| if (minuteTok.value.length !== 2) { | ||
| throw new ParseError( | ||
| `Invalid time format: "${trimmed}". Minutes must be 2 digits (e.g., "9:07" not "9:7")`, | ||
| i | ||
| ); | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| let hour; | ||
| let minute = 0; | ||
| let second; | ||
| let fraction; | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const secondTok = eat("Number" /* Number */); | ||
| second = toInt(secondTok.value, "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| const numLen = hourTok.value.length; | ||
| if (!at("Colon" /* Colon */) && (numLen === 4 || numLen === 6)) { | ||
| const timeStr = hourTok.value; | ||
| hour = toInt(timeStr.substring(0, 2), "hour", i); | ||
| minute = toInt(timeStr.substring(2, 4), "minute", i); | ||
| if (numLen === 6) { | ||
| second = toInt(timeStr.substring(4, 6), "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| } | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Dot" /* Dot */) || tryEat("Comma" /* Comma */)) { | ||
@@ -686,2 +683,28 @@ const fracTok = eat("Number" /* Number */); | ||
| } | ||
| } else { | ||
| hour = toInt(hourTok.value, "hour", i); | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const minuteTok = eat("Number" /* Number */); | ||
| minute = toInt(minuteTok.value, "minute", i); | ||
| if (minuteTok.value.length !== 2) { | ||
| throw new ParseError( | ||
| `Invalid time format: "${trimmed}". Minutes must be 2 digits (e.g., "9:07" not "9:7")`, | ||
| i | ||
| ); | ||
| } | ||
| if (minute < 0 || minute > 59) { | ||
| throw new ParseError(`Invalid minute: ${minute}. Minutes must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Colon" /* Colon */)) { | ||
| const secondTok = eat("Number" /* Number */); | ||
| second = toInt(secondTok.value, "second", i); | ||
| if (second < 0 || second > 59) { | ||
| throw new ParseError(`Invalid second: ${second}. Seconds must be between 00-59`, i); | ||
| } | ||
| if (tryEat("Dot" /* Dot */) || tryEat("Comma" /* Comma */)) { | ||
| const fracTok = eat("Number" /* Number */); | ||
| fraction = fracTok.value; | ||
| } | ||
| } | ||
| } | ||
| } | ||
@@ -688,0 +711,0 @@ let ampmStr; |
| import type { TimeAst } from './parser-types.js'; | ||
| /** | ||
| * Parse a time-of-day string from multiple common formats. | ||
| * Supports: locale time ("9:07 AM"), 24h ("09:00", "14:30"), short 24h ("9:00"), | ||
| * and 12h with lowercase period ("9:07 am"). | ||
| * Supports: locale time ("9:07 AM"), 24h ("09:00", "14:30"), ISO 8601 basic format ("1430"), | ||
| * short 24h ("9:00"), bare hours ("7", "7 AM"), and 12h with lowercase period ("9:07 am"). | ||
| * | ||
@@ -12,4 +12,6 @@ * TAA (LLM) often generates time in 24h format ("09:00") instead of the locale | ||
| * - Locale time (12-hour with AM/PM): "9:07 AM", "2:30 PM", "02:30PM", "2:30 p.m." | ||
| * - 24-hour format: "09:00", "14:30", "23:59" | ||
| * - 24-hour format (extended): "09:00", "14:30", "23:59" | ||
| * - ISO 8601 basic format (compact): "1430", "0900", "143045", "143045.123" | ||
| * - Short 24-hour (single digit hour): "9:00", "9:30" | ||
| * - Bare hours (defaults to :00): "7" (→ 7:00), "0" (→ 0:00), "7 AM" (→ 7:00 AM) | ||
| * - Lowercase am/pm: "9:07 am", "2:30 pm" | ||
@@ -16,0 +18,0 @@ * - With optional seconds: "2:30:45 PM", "14:30:45" |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"parseTimeString.d.ts","sourceRoot":"","sources":["../../src/parseTimeString.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA2JtD"} | ||
| {"version":3,"file":"parseTimeString.d.ts","sourceRoot":"","sources":["../../src/parseTimeString.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAmMtD"} |
+1
-1
| { | ||
| "name": "@taskade/temporal-parser", | ||
| "version": "1.2.0", | ||
| "version": "1.2.1", | ||
| "description": "A lexer/parser based temporal expression parser for ISO 8601 and IXDTF formats", | ||
@@ -5,0 +5,0 @@ "type": "module", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
226313
3.4%2136
2.3%