qte 0.0.1 → 0.1.0

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
@@ -1,10 +1,280 @@
1
-
2
1
  <div align="center">
3
- <h1 align="center">qte</h1>
2
+ <h1 align="center">⏱️ <code>qte</code></h1>
4
3
 
5
4
  <p align="center">
6
- <strong>Time conversion utilities</strong>
5
+ <strong>Parsing and formatting for human-readable time expressions.</strong>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/qte"><img src="https://img.shields.io/npm/v/qte" alt="npm version"></a>
10
+ <a href="https://pkg-size.dev/qte"><img src="https://pkg-size.dev/badge/bundle/qte" alt="bundle size"></a>
11
+ <a href="https://github.com/adelrodriguez/qte/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/qte" alt="license"></a>
7
12
  </p>
8
13
  </div>
9
14
 
10
- Made with [🥐 `pastry`](https://github.com/adelrodriguez/pastry)
15
+ ## Features
16
+
17
+ - Parse time strings into any unit (milliseconds, seconds, minutes, hours, days, weeks, months, years)
18
+ - Compound expressions (`"1h 30m"`, `"1 day, 6 hours"`)
19
+ - Format milliseconds back to human-readable strings with configurable precision
20
+ - Tree-shakeable named exports
21
+ - TypeScript `TimeExpression` type with compile-time checking and `isTimeExpression` / `isCompoundTimeExpression` guards
22
+ - Zero dependencies
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ npm install qte
28
+ # or
29
+ bun add qte
30
+ # or
31
+ pnpm add qte
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ```ts
37
+ import { parse, format, ms, seconds, MS_PER_WEEK } from "qte"
38
+
39
+ parse("2 days, 6 hours") // 194_400_000
40
+ format(3_600_000) // "1h"
41
+ format(5_432_100, { precision: 3 }) // "1h 30m 32s"
42
+ format(5 * MS_PER_WEEK, { precision: 2 }) // "1mo 1w" (approximate)
43
+ ms("1h") // 3_600_000
44
+ seconds("30m") // 1800
45
+ ```
46
+
47
+ ## API
48
+
49
+ ### `parse`
50
+
51
+ Parses a time expression and returns the value in milliseconds.
52
+
53
+ ```ts
54
+ import { parse } from "qte"
55
+
56
+ parse("1h") // 3_600_000
57
+ parse("30s") // 30_000
58
+ parse("1h 30m") // 5_400_000
59
+ parse("1 day, 6 hours, 30 minutes") // 109_800_000
60
+ ```
61
+
62
+ ### `format`
63
+
64
+ Converts milliseconds to a human-readable time expression.
65
+
66
+ ```ts
67
+ import { format } from "qte"
68
+
69
+ format(3_600_000) // "1h"
70
+ format(500) // "500ms"
71
+ format(0) // "0ms"
72
+ format(-3_600_000) // "-1h"
73
+ ```
74
+
75
+ #### Options
76
+
77
+ | Option | Type | Default | Description |
78
+ | ----------- | --------- | ------- | ----------------------------------------- |
79
+ | `long` | `boolean` | `false` | Use verbose format (`"1 hour"` vs `"1h"`) |
80
+ | `precision` | `number` | `1` | Maximum number of unit segments to output |
81
+
82
+ ```ts
83
+ format(3_600_000, { long: true }) // "1 hour"
84
+ format(5_432_100, { precision: 3 }) // "1h 30m 32s"
85
+ format(5_400_000, { long: true, precision: 2 }) // "1 hour 30 minutes"
86
+ ```
87
+
88
+ #### Precision
89
+
90
+ When `precision` is `1` (the default), the value is rounded to the single largest applicable unit. Higher values decompose the duration into multiple segments, with the last segment rounded to absorb the remainder.
91
+
92
+ If the value has fewer meaningful segments than the requested precision, only the meaningful segments are returned:
93
+
94
+ ```ts
95
+ format(3_600_000, { precision: 5 }) // "1h"
96
+ format(500, { precision: 10 }) // "500ms"
97
+ ```
98
+
99
+ Month/year units use fixed average durations, so low precision can produce noticeable approximation around week/month boundaries:
100
+
101
+ ```ts
102
+ format(5 * MS_PER_WEEK, { precision: 2 }) // "1mo 1w" (approximate)
103
+ ```
104
+
105
+ The output of `format` is always a valid input for `parse`:
106
+
107
+ ```ts
108
+ const expr = format(5_400_000, { precision: 2 }) // "1h 30m"
109
+ parse(expr) // 5_400_000
110
+
111
+ const negativeExpr = format(-5_400_000, { precision: 2 }) // "-1h 30m"
112
+ parse(negativeExpr) // -5_400_000
113
+ ```
114
+
115
+ ### Unit Functions
116
+
117
+ Each function parses a single time expression and returns the value in the named unit. For compound expressions, use `parse` instead.
118
+
119
+ ```ts
120
+ import { ms, seconds, minutes, hours, days, weeks, months, years } from "qte"
121
+
122
+ ms("1s") // 1000
123
+ seconds("1h") // 3600
124
+ seconds("500ms") // 0.5
125
+ minutes("2h") // 120
126
+ hours("1d") // 24
127
+ days("1w") // 7
128
+ weeks("1y") // 52.1775
129
+ ```
130
+
131
+ ### `isTimeExpression`
132
+
133
+ Type guard that checks if a string is a valid single time expression. Returns `false` for compound expressions like `"1h 30m"`. Never throws.
134
+
135
+ ```ts
136
+ import { isTimeExpression } from "qte"
137
+
138
+ isTimeExpression("1h") // true
139
+ isTimeExpression("500ms") // true
140
+ isTimeExpression("1h 30m") // false (use isCompoundTimeExpression)
141
+ isTimeExpression("hello") // false
142
+
143
+ const input: string = getUserInput()
144
+ if (isTimeExpression(input)) {
145
+ ms(input) // TypeScript knows `input` is TimeExpression
146
+ }
147
+ ```
148
+
149
+ ### `isCompoundTimeExpression`
150
+
151
+ Checks if a string is a valid time expression (simple or compound). Never throws.
152
+
153
+ ```ts
154
+ import { isCompoundTimeExpression } from "qte"
155
+
156
+ isCompoundTimeExpression("1h") // true
157
+ isCompoundTimeExpression("1h 30m") // true
158
+ isCompoundTimeExpression("hello") // false
159
+
160
+ const input: string = getUserInput()
161
+ if (isCompoundTimeExpression(input)) {
162
+ parse(input) // input is a valid time expression
163
+ }
164
+ ```
165
+
166
+ ### Constants
167
+
168
+ Millisecond-based conversion factors for custom arithmetic (e.g. computing a cache TTL or rate limit window):
169
+
170
+ ```ts
171
+ import {
172
+ MS_PER_SECOND, // 1_000
173
+ MS_PER_MINUTE, // 60_000
174
+ MS_PER_HOUR, // 3_600_000
175
+ MS_PER_DAY, // 86_400_000
176
+ MS_PER_WEEK, // 604_800_000
177
+ MS_PER_MONTH, // 2_629_800_000
178
+ MS_PER_YEAR, // 31_557_600_000
179
+ } from "qte"
180
+ ```
181
+
182
+ ## Compound Expressions
183
+
184
+ The parser supports multi-part expressions. Parts are summed together.
185
+
186
+ ```ts
187
+ // Space-separated
188
+ parse("1h 30m") // 5_400_000
189
+
190
+ // Comma-separated (single commas only)
191
+ parse("1h, 30m") // 5_400_000
192
+
193
+ // Concatenated (no separator)
194
+ parse("1h30m") // 5_400_000
195
+
196
+ // Long form
197
+ parse("1 hour 30 minutes") // 5_400_000
198
+ parse("1 year 2 weeks 5 days") // 32_594_400_000
199
+
200
+ // Duplicate units are additive
201
+ parse("1h 2h") // 10_800_000
202
+
203
+ // Order doesn't matter
204
+ parse("30m 1h") // 5_400_000
205
+ ```
206
+
207
+ Malformed delimiter punctuation is rejected (`",1h"`, `"1h,"`, `"1h,,30m"`, and `"1h, ,30m"` are invalid).
208
+ Numeric token pattern is `[+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?`, so exponent notation is supported.
209
+
210
+ ### Supported Units
211
+
212
+ All units are case-insensitive. Spaces between number and unit are optional.
213
+
214
+ | Unit | Short | Aliases |
215
+ | ------------ | ----- | ---------------------------------------------- |
216
+ | Milliseconds | `ms` | `milliseconds`, `millisecond`, `msecs`, `msec` |
217
+ | Seconds | `s` | `seconds`, `second`, `secs`, `sec` |
218
+ | Minutes | `m` | `minutes`, `minute`, `mins`, `min` |
219
+ | Hours | `h` | `hours`, `hour`, `hrs`, `hr` |
220
+ | Days | `d` | `days`, `day` |
221
+ | Weeks | `w` | `weeks`, `week` |
222
+ | Months | `mo` | `months`, `month` |
223
+ | Years | `y` | `years`, `year`, `yrs`, `yr` |
224
+
225
+ ### Signed Expressions
226
+
227
+ A leading sign applies to the entire compound expression when later parts are unsigned. Explicit signs on later segments override this and are evaluated per segment.
228
+
229
+ ```ts
230
+ parse("-1h 30m") // -5_400_000
231
+ parse("+1h 30m") // 5_400_000
232
+ parse("-1h +30m") // -1_800_000
233
+ parse("-1h -30m") // -5_400_000
234
+ parse("-1h 30m -10m") // -2_400_000
235
+ parse("-1h 30m +10m") // -1_200_000
236
+ parse("1h-30m") // 1_800_000
237
+ parse("1h+30m") // 5_400_000
238
+ ```
239
+
240
+ ## Types
241
+
242
+ ```ts
243
+ import type { TimeExpression, FormatOptions, Unit } from "qte"
244
+ ```
245
+
246
+ - **`TimeExpression`** — A template literal type for single time expressions (`"1h"`, `"30s"`, `"500ms"`). Rejects invalid string literals at compile time. Used by unit functions (`ms`, `seconds`, etc.).
247
+ - **`FormatOptions`** — Options for `format()` (`long`, `precision`).
248
+ - **`Unit`** — Union of all recognized unit strings (e.g. `"hours"`, `"h"`, `"hr"`).
249
+
250
+ Use the type guards to validate strings at runtime:
251
+
252
+ ```ts
253
+ const input: string = getUserInput()
254
+ if (isTimeExpression(input)) {
255
+ ms(input) // `input` is narrowed to TimeExpression
256
+ }
257
+ if (isCompoundTimeExpression(input)) {
258
+ parse(input) // input is a valid expression (simple or compound)
259
+ }
260
+ ```
261
+
262
+ ## Error Handling
263
+
264
+ **`parse` and unit functions:**
265
+
266
+ - Throw a `TypeError` if the input is not a string, is empty, or exceeds 200 characters.
267
+ - Return `NaN` if the string cannot be parsed.
268
+
269
+ **`format`:**
270
+
271
+ - Throws a `TypeError` if the input is not a finite number (`Infinity`, `-Infinity`, `NaN`).
272
+ - Throws a `RangeError` if `precision` is not a finite positive integer (e.g. `0`, negative numbers, `NaN`, `Infinity`, or decimals).
273
+
274
+ **`isTimeExpression` and `isCompoundTimeExpression`:**
275
+
276
+ - Never throw. Return `false` for any invalid input.
277
+
278
+ ## License
279
+
280
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,2 +1,244 @@
1
- declare function main(): string;
2
- export { main };
1
+ /** Milliseconds in one second (`1_000`). */
2
+ declare const MS_PER_SECOND = 1e3;
3
+ /** Milliseconds in one minute (`60_000`). */
4
+ declare const MS_PER_MINUTE: number;
5
+ /** Milliseconds in one hour (`3_600_000`). */
6
+ declare const MS_PER_HOUR: number;
7
+ /** Milliseconds in one day (`86_400_000`). */
8
+ declare const MS_PER_DAY: number;
9
+ /** Milliseconds in one week (`604_800_000`). */
10
+ declare const MS_PER_WEEK: number;
11
+ /** Milliseconds in one year (`31_557_600_000`), based on 365.25 days. */
12
+ declare const MS_PER_YEAR: number;
13
+ /** Milliseconds in one month (`2_629_800_000`), derived as one twelfth of a year. */
14
+ declare const MS_PER_MONTH: number;
15
+ /** Year unit aliases. */
16
+ type Years = "years" | "year" | "yrs" | "yr" | "y";
17
+ /** Month unit aliases. */
18
+ type Months = "months" | "month" | "mo";
19
+ /** Week unit aliases. */
20
+ type Weeks = "weeks" | "week" | "w";
21
+ /** Day unit aliases. */
22
+ type Days = "days" | "day" | "d";
23
+ /** Hour unit aliases. */
24
+ type Hours = "hours" | "hour" | "hrs" | "hr" | "h";
25
+ /** Minute unit aliases. */
26
+ type Minutes = "minutes" | "minute" | "mins" | "min" | "m";
27
+ /** Second unit aliases. */
28
+ type Seconds = "seconds" | "second" | "secs" | "sec" | "s";
29
+ /** Millisecond unit aliases. */
30
+ type Milliseconds = "milliseconds" | "millisecond" | "msecs" | "msec" | "ms";
31
+ /** Union of all recognized time unit strings. */
32
+ type Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Milliseconds;
33
+ /** Any casing variant of a time unit (lowercase, Capitalized, UPPERCASE). */
34
+ type UnitAnyCase = Unit | Capitalize<Unit> | Uppercase<Unit>;
35
+ /**
36
+ * A single time expression: a bare number, or a number followed by a unit
37
+ * (with or without a space).
38
+ */
39
+ type TimeExpression = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
40
+ /** Options for {@link format}. */
41
+ interface FormatOptions {
42
+ /** Use verbose formatting (`"1 hour"` instead of `"1h"`). Defaults to `false`. */
43
+ long?: boolean;
44
+ /** Maximum number of unit segments to include. Defaults to `1`. */
45
+ precision?: number;
46
+ }
47
+ /**
48
+ * Format a millisecond value into a human-readable time expression.
49
+ *
50
+ * The returned string can be passed back into {@link parse} for
51
+ * round-trip conversion.
52
+ *
53
+ * @param milliseconds - The value in milliseconds to format
54
+ * @param options - Formatting options
55
+ * @returns A formatted time expression string
56
+ * @throws {TypeError} If the input is not a finite number
57
+ * @throws {RangeError} If `options.precision` is not a finite positive integer
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * format(3_600_000) // "1h"
62
+ * format(3_600_000, { long: true }) // "1 hour"
63
+ * format(500) // "500ms"
64
+ * format(5_432_100, { precision: 3 }) // "1h 30m 32s"
65
+ * ```
66
+ */
67
+ declare function format(milliseconds: number, options?: FormatOptions): string;
68
+ /**
69
+ * Check whether a string is a valid single time expression without throwing.
70
+ *
71
+ * Acts as a TypeScript type guard — when it returns `true`, the input is
72
+ * narrowed to {@link TimeExpression}. Unlike {@link isCompoundTimeExpression},
73
+ * this rejects compound expressions such as `"1h 30m"`.
74
+ *
75
+ * @param value - The string to validate
76
+ * @returns `true` if the string is a valid single time expression
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * isTimeExpression("1h") // true
81
+ * isTimeExpression("500ms") // true
82
+ * isTimeExpression("1h 30m") // false (compound)
83
+ * isTimeExpression("hello") // false
84
+ *
85
+ * const input: string = getUserInput()
86
+ * if (isTimeExpression(input)) {
87
+ * ms(input) // TypeScript knows `input` is TimeExpression
88
+ * }
89
+ * ```
90
+ */
91
+ declare function isTimeExpression(value: string): value is TimeExpression;
92
+ /**
93
+ * Check whether a string is a valid time expression (simple or compound)
94
+ * without throwing.
95
+ *
96
+ * This accepts both simple expressions (`"1h"`) and compound expressions
97
+ * (`"1h 30m"`).
98
+ *
99
+ * @param value - The string to validate
100
+ * @returns `true` if the string is a valid time expression
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * isCompoundTimeExpression("1h") // true
105
+ * isCompoundTimeExpression("1h 30m") // true
106
+ * isCompoundTimeExpression("hello") // false
107
+ * isCompoundTimeExpression("") // false
108
+ *
109
+ * const input: string = getUserInput()
110
+ * if (isCompoundTimeExpression(input)) {
111
+ * parse(input) // input is a valid time expression
112
+ * }
113
+ * ```
114
+ */
115
+ declare function isCompoundTimeExpression(value: string): boolean;
116
+ /**
117
+ * Parse a time expression string into milliseconds.
118
+ *
119
+ * Accepts both simple (`"1h"`) and compound (`"1h 30m"`) expressions.
120
+ * Parts are summed together. Duplicate units are additive.
121
+ * Supports space separators, a single comma separator, or no separator.
122
+ * Numeric tokens support optional exponent notation (e.g. `"1e3ms"`).
123
+ * A leading sign on a compound expression applies to the whole expression
124
+ * unless later parts declare their own explicit signs.
125
+ *
126
+ * @param value - A time expression string to parse
127
+ * @returns The total value in milliseconds, or `NaN` if the string cannot be parsed
128
+ * @throws {TypeError} If the input is not a string, is empty, or exceeds 200 characters
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * parse("1h") // 3_600_000
133
+ * parse("30s") // 30_000
134
+ * parse("1h 30m") // 5_400_000
135
+ * parse("1 day, 6 hours, 30 minutes") // 109_800_000
136
+ * ```
137
+ */
138
+ declare function parse(value: string): number;
139
+ /**
140
+ * Parse a time expression and return the value in milliseconds.
141
+ *
142
+ * @param value - A time expression string
143
+ * @returns The value in milliseconds
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * ms("1s") // 1000
148
+ * ms("5m") // 300_000
149
+ * ms("1h") // 3_600_000
150
+ * ```
151
+ */
152
+ declare function ms(value: TimeExpression): number;
153
+ /**
154
+ * Parse a time expression and return the value in seconds.
155
+ *
156
+ * @param value - A time expression string
157
+ * @returns The value in seconds
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * seconds("1h") // 3600
162
+ * seconds("500ms") // 0.5
163
+ * ```
164
+ */
165
+ declare function seconds(value: TimeExpression): number;
166
+ /**
167
+ * Parse a time expression and return the value in minutes.
168
+ *
169
+ * @param value - A time expression string
170
+ * @returns The value in minutes
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * minutes("2h") // 120
175
+ * minutes("30s") // 0.5
176
+ * ```
177
+ */
178
+ declare function minutes(value: TimeExpression): number;
179
+ /**
180
+ * Parse a time expression and return the value in hours.
181
+ *
182
+ * @param value - A time expression string
183
+ * @returns The value in hours
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * hours("1d") // 24
188
+ * hours("30m") // 0.5
189
+ * ```
190
+ */
191
+ declare function hours(value: TimeExpression): number;
192
+ /**
193
+ * Parse a time expression and return the value in days.
194
+ *
195
+ * @param value - A time expression string
196
+ * @returns The value in days
197
+ *
198
+ * @example
199
+ * ```ts
200
+ * days("1w") // 7
201
+ * days("12h") // 0.5
202
+ * ```
203
+ */
204
+ declare function days(value: TimeExpression): number;
205
+ /**
206
+ * Parse a time expression and return the value in weeks.
207
+ *
208
+ * @param value - A time expression string
209
+ * @returns The value in weeks
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * weeks("14d") // 2
214
+ * weeks("1y") // 52.1775
215
+ * ```
216
+ */
217
+ declare function weeks(value: TimeExpression): number;
218
+ /**
219
+ * Parse a time expression and return the value in months.
220
+ *
221
+ * @param value - A time expression string
222
+ * @returns The value in months
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * months("1y") // 12
227
+ * months("60d") // ~1.97
228
+ * ```
229
+ */
230
+ declare function months(value: TimeExpression): number;
231
+ /**
232
+ * Parse a time expression and return the value in years.
233
+ *
234
+ * @param value - A time expression string
235
+ * @returns The value in years
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * years("365.25d") // 1
240
+ * years("6mo") // 0.5
241
+ * ```
242
+ */
243
+ declare function years(value: TimeExpression): number;
244
+ export { years, weeks, seconds, parse, ms, months, minutes, isTimeExpression, isCompoundTimeExpression, hours, format, days, Years, Weeks, Unit, TimeExpression, Seconds, Months, Minutes, Milliseconds, MS_PER_YEAR, MS_PER_WEEK, MS_PER_SECOND, MS_PER_MONTH, MS_PER_MINUTE, MS_PER_HOUR, MS_PER_DAY, Hours, FormatOptions, Days };
package/dist/index.js CHANGED
@@ -1,10 +1 @@
1
- // src/index.ts
2
- function main() {
3
- return "Let's bake some pastry! \uD83E\uDD50";
4
- }
5
- export {
6
- main
7
- };
8
-
9
- //# debugId=B3F3B1D74DE4157564756E2164756E21
10
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWwogICAgImV4cG9ydCBmdW5jdGlvbiBtYWluKCkge1xuICByZXR1cm4gXCJMZXQncyBiYWtlIHNvbWUgcGFzdHJ5ISDwn6WQXCJcbn1cbiIKICBdLAogICJtYXBwaW5ncyI6ICI7QUFBTyxTQUFTLElBQUksR0FBRztBQUFBLEVBQ3JCLE9BQU87QUFBQTsiLAogICJkZWJ1Z0lkIjogIkIzRjNCMUQ3NERFNDE1NzU2NDc1NkUyMTY0NzU2RTIxIiwKICAibmFtZXMiOiBbXQp9
1
+ var B=1000,X=60000,F=3600000,G=86400000,H=604800000,f=31557600000,L=2629800000;var K=[{aliases:["years","year","yrs","yr","y"],long:"year",longPlural:"years",ms:f,short:"y"},{aliases:["months","month","mo"],long:"month",longPlural:"months",ms:L,short:"mo"},{aliases:["weeks","week","w"],long:"week",longPlural:"weeks",ms:H,short:"w"},{aliases:["days","day","d"],long:"day",longPlural:"days",ms:G,short:"d"},{aliases:["hours","hour","hrs","hr","h"],long:"hour",longPlural:"hours",ms:F,short:"h"},{aliases:["minutes","minute","mins","min","m"],long:"minute",longPlural:"minutes",ms:X,short:"m"},{aliases:["seconds","second","secs","sec","s"],long:"second",longPlural:"seconds",ms:B,short:"s"},{aliases:["milliseconds","millisecond","msecs","msec","ms"],long:"millisecond",longPlural:"milliseconds",ms:1,short:"ms"}];function S(y){return y.replaceAll(/[.*+?^${}()|[\]\\]/g,"\\$&")}var C=[...new Set(K.flatMap((y)=>y.aliases))],T=new Map(K.flatMap((y)=>y.aliases.map((k)=>[k,y.ms]))),V=C.toSorted((y,k)=>k.length-y.length).map((y)=>S(y)).join("|");function I(y){return T.get(y)??Number.NaN}function P(y){let k=K.at(y);if(!k)throw Error(`Invalid unit index: ${y}`);return k}function Z(y,k,_){if(_){let Y=Math.abs(y)===1?k.long:k.longPlural;return`${y} ${Y}`}return`${y}${k.short}`}function c(y,k){if(typeof y!=="number"||!Number.isFinite(y))throw TypeError(`Value provided to format() must be a finite number. Received: ${String(y)}`);let _=k?.long??!1,Y=k?.precision??1;if(!Number.isFinite(Y)||!Number.isInteger(Y)||Y<1)throw RangeError(`Option "precision" must be a finite positive integer. Received: ${String(Y)}`);if(y===0)return Z(0,P(K.length-1),_);let $=y<0,D=Math.abs(y);if(Y===1)return d(y,D,_);return m(D,$,_,Y)}function d(y,k,_){let Y=y<0?-1:1;for(let q of K)if(k>=q.ms){let M=Math.round(k/q.ms),j=M===0?0:Y*M;return Z(j,q,_)}let $=P(K.length-1),D=Math.round(k/$.ms),z=D===0?0:Y*D;return Z(z,$,_)}function m(y,k,_,Y){let $=y,D=[];for(let M=0;M<K.length&&D.length<Y;M+=1){let j=P(M);if(D.length===Y-1){let J=Math.round($/j.ms);if(J>0){D.push({unitIdx:M,value:J});break}continue}let w=Math.floor($/j.ms);if(w>0)D.push({unitIdx:M,value:w}),$-=w*j.ms}if(D.length===0){let M=P(K.length-1),j=Math.round(y/M.ms);D.push({unitIdx:K.length-1,value:j})}for(let M=D.length-1;M>=0;M-=1){let j=D[M],w=P(j.unitIdx),J=j.unitIdx-1;if(J<0)continue;let Q=P(J).ms/w.ms;if(j.value>=Q){let R=Math.floor(j.value/Q);j.value-=R*Q;let W=M>0?D[M-1]:void 0;if(W&&W.unitIdx===J)W.value+=R;else D.splice(M,0,{unitIdx:J,value:R}),M+=1}}while(D.length>1){let M=D.at(-1);if(!M||M.value!==0)break;D.pop()}if(D.length===0)return Z(0,P(K.length-1),_);if(D.every((M)=>M.value===0))return Z(0,P(K.length-1),_);let q=D.map((M)=>Z(M.value,P(M.unitIdx),_)).join(" ");return k?`-${q}`:q}var h=200,x=new RegExp(`([+-]?\\d*\\.?\\d+(?:e[+-]?\\d+)?)\\s*(${V})?`,"gi"),U=/^\s*$/,o=/^\s*,\s*$/;function p(y,k){if(U.test(y))return!0;if(k)return!1;return o.test(y)}function O(y){if(typeof y!=="string"||y.length===0||y.length>h)throw TypeError(`Value provided to parse() must be a string with length between 1 and ${h}. Received: ${String(y)}`);x.lastIndex=0;let k=0,_=0,Y=0,$=0,D=!1,z=!1,q=!1,M;while((M=x.exec(y))!==null){let A=y.slice(Y,M.index);if(!p(A,$===0))return Number.NaN;let Q=M[1]??"",R=M[2];if(!R)D=!0;let W=Q.startsWith("-")||Q.startsWith("+");if($===0)z=W;else if(W)q=!0;let E=Number.parseFloat(Q),b=R?I(R.toLowerCase()):1;if(!Number.isFinite(E)||Number.isNaN(b))return Number.NaN;let N=E*b;if(!Number.isFinite(N))return Number.NaN;if(k+=N,!Number.isFinite(k))return Number.NaN;if(_+=Math.abs(N),!Number.isFinite(_))return Number.NaN;Y=M.index+M[0].length,$+=1}if($===0)return Number.NaN;if($>1&&D)return Number.NaN;let j=y.slice(Y);if(!U.test(j))return Number.NaN;let w=y.trimStart(),J=w.startsWith("-")||w.startsWith("+");if($>1&&J&&z&&!q)return w.startsWith("-")?-_:_;return k}function v(y){return O(y)}function g(y){return O(y)/B}function r(y){return O(y)/X}function l(y){return O(y)/F}function s(y){return O(y)/G}function u(y){return O(y)/H}function n(y){return O(y)/L}function a(y){return O(y)/f}var t=new RegExp(`^[+-]?\\d*\\.?\\d+(?:e[+-]?\\d+)?(?: ?(?:${V}))?$`,"i");function i(y){try{if(!t.test(y))return!1;return!Number.isNaN(O(y))}catch{return!1}}function e(y){try{return!Number.isNaN(O(y))}catch{return!1}}export{a as years,u as weeks,g as seconds,O as parse,v as ms,n as months,r as minutes,i as isTimeExpression,e as isCompoundTimeExpression,l as hours,c as format,s as days,f as MS_PER_YEAR,H as MS_PER_WEEK,B as MS_PER_SECOND,L as MS_PER_MONTH,X as MS_PER_MINUTE,F as MS_PER_HOUR,G as MS_PER_DAY};
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "qte",
3
- "version": "0.0.1",
4
- "description": "Time conversion utilities",
3
+ "version": "0.1.0",
4
+ "description": "Parse human-readable time expressions into any unit, and format durations into human-readable strings",
5
5
  "keywords": [
6
- "bun",
7
- "library",
8
- "template"
6
+ "convert",
7
+ "duration",
8
+ "format",
9
+ "human-readable",
10
+ "milliseconds",
11
+ "ms",
12
+ "parse",
13
+ "time"
9
14
  ],
10
15
  "homepage": "https://github.com/adelrodriguez/qte#readme",
11
16
  "bugs": {
@@ -15,18 +20,27 @@
15
20
  "author": "Adel Rodríguez",
16
21
  "repository": {
17
22
  "type": "git",
18
- "url": "https://github.com/adelrodriguez/qte.git"
23
+ "url": "git+https://github.com/adelrodriguez/qte.git"
19
24
  },
20
25
  "files": [
21
26
  "dist"
22
27
  ],
23
28
  "type": "module",
24
- "module": "src/index.ts",
29
+ "sideEffects": false,
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js"
36
+ }
37
+ },
25
38
  "scripts": {
26
39
  "build": "bunup",
40
+ "build:debug": "bunup --sourcemap inline --no-minify",
27
41
  "bump:deps": "bun update --interactive",
28
42
  "check": "adamantite check",
29
- "dev": "bunup --watch",
43
+ "dev": "bunup --watch --sourcemap inline --no-minify",
30
44
  "fix": "adamantite fix",
31
45
  "release": "changeset publish",
32
46
  "init": "bun run --bun scripts/init.ts",