postgres-interval 4.0.1 → 4.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.
Files changed (4) hide show
  1. package/index.d.ts +18 -0
  2. package/index.js +37 -31
  3. package/package.json +1 -1
  4. package/readme.md +10 -0
package/index.d.ts CHANGED
@@ -61,6 +61,24 @@ declare namespace PostgresInterval {
61
61
  * ```
62
62
  */
63
63
  toISOStringShort(): string;
64
+ /**
65
+ * Returns a [`Temporal.Duration`](https://tc39.es/proposal-temporal/docs/duration.html) representing the interval.
66
+ *
67
+ * Requires `globalThis.Temporal` (Node 26+, or a polyfill assigned to the global). Throws otherwise.
68
+ *
69
+ * Postgres mixed-sign intervals (e.g. `1 mon -1 days`) throw a `RangeError`, because `Temporal.Duration` requires a single sign across all fields.
70
+ *
71
+ * The `Temporal` types are not yet in the default TypeScript lib. For this signature to resolve, your project needs Temporal lib types (the TypeScript lib once available, or `@js-temporal/polyfill` types).
72
+ *
73
+ * ```js
74
+ * var parse = require('postgres-interval')
75
+ * var interval = parse('01:02:03')
76
+ * // => { hours: 1, minutes: 2, seconds: 3 }
77
+ * interval.toTemporalDuration().toString()
78
+ * // PT1H2M3S
79
+ * ```
80
+ */
81
+ toTemporalDuration(): Temporal.Duration;
64
82
  }
65
83
  }
66
84
 
package/index.js CHANGED
@@ -93,6 +93,25 @@ PostgresInterval.prototype.toISOStringShort = function () {
93
93
  return toISOString.call(this, { short: true })
94
94
  }
95
95
 
96
+ PostgresInterval.prototype.toTemporalDuration = function () {
97
+ if (typeof globalThis.Temporal === 'undefined') {
98
+ throw new Error('Temporal is not available. It ships unflagged in Node 26+. On older runtimes, install a polyfill (e.g. @js-temporal/polyfill) and assign it to globalThis.Temporal.')
99
+ }
100
+
101
+ const totalMicroseconds = Math.round(this.milliseconds * 1000)
102
+
103
+ return globalThis.Temporal.Duration.from({
104
+ years: this.years,
105
+ months: this.months,
106
+ days: this.days,
107
+ hours: this.hours,
108
+ minutes: this.minutes,
109
+ seconds: this.seconds,
110
+ milliseconds: Math.trunc(totalMicroseconds / 1000),
111
+ microseconds: totalMicroseconds % 1000
112
+ })
113
+ }
114
+
96
115
  function toISOString ({ short }) {
97
116
  let datePart = ''
98
117
 
@@ -157,34 +176,27 @@ function readNextNum (interval) {
157
176
  }
158
177
 
159
178
  function parseMillisecond (interval) {
179
+ const previousPosition = position.value
160
180
  const currentValue = readNextNum(interval)
161
-
162
- if (currentValue < 10) {
163
- return currentValue * 100
164
- }
165
-
166
- if (currentValue < 100) {
167
- return currentValue * 10
168
- }
169
-
170
- if (currentValue < 1000) {
171
- return currentValue
172
- }
173
-
174
- if (currentValue < 10000) {
175
- return currentValue / 10
176
- }
177
-
178
- if (currentValue < 100000) {
179
- return currentValue / 100
180
- }
181
-
182
- if (currentValue < 1000000) {
183
- return currentValue / 1000
181
+ const valueStringLength = position.value - previousPosition
182
+
183
+ switch (valueStringLength) {
184
+ case 1:
185
+ return currentValue * 100
186
+ case 2:
187
+ return currentValue * 10
188
+ case 3:
189
+ return currentValue
190
+ case 4:
191
+ return currentValue / 10
192
+ case 5:
193
+ return currentValue / 100
194
+ case 6:
195
+ return currentValue / 1000
184
196
  }
185
197
 
186
198
  // slow path
187
- const remainder = currentValue.toString().length - 3
199
+ const remainder = valueStringLength - 3
188
200
  return currentValue / Math.pow(10, remainder)
189
201
  }
190
202
 
@@ -205,13 +217,7 @@ function parse (instance, interval) {
205
217
  nextNegative = -1
206
218
  position.value++
207
219
  continue
208
- } else if (char === '+') {
209
- position.value++
210
- continue
211
- } else if (char === ' ') {
212
- position.value++
213
- continue
214
- } else if (char < '0' || char > '9') {
220
+ } else if (!(char >= '0' && char <= '9')) {
215
221
  position.value++
216
222
  continue
217
223
  } else {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "postgres-interval",
3
3
  "main": "index.js",
4
- "version": "4.0.1",
4
+ "version": "4.1.0",
5
5
  "description": "Parse Postgres interval columns",
6
6
  "license": "MIT",
7
7
  "repository": "bendrucker/postgres-interval",
package/readme.md CHANGED
@@ -57,6 +57,16 @@ Also available as `interval.toISO()` for backwards compatibility.
57
57
 
58
58
  Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string shortened to minimum length, for example `PT9M`.
59
59
 
60
+ #### `interval.toTemporalDuration()` -> `Temporal.Duration`
61
+
62
+ Returns a [`Temporal.Duration`](https://tc39.es/proposal-temporal/docs/duration.html) representing the interval.
63
+
64
+ Requires `globalThis.Temporal`. It ships unflagged in Node 26+. On older runtimes, install a polyfill such as [`@js-temporal/polyfill`](https://www.npmjs.com/package/@js-temporal/polyfill) and assign it to `globalThis.Temporal`. The method throws if `Temporal` is unavailable.
65
+
66
+ Postgres mixed-sign intervals (e.g. `1 mon -1 days`) throw a `RangeError`. `Temporal.Duration` requires all fields to share a single sign, which these intervals violate.
67
+
68
+ The `Temporal` types are not yet in the default TypeScript lib. To resolve the return type, your project needs Temporal lib types: the TypeScript lib once available, or the `@js-temporal/polyfill` types. This package adds no type dependency.
69
+
60
70
  ## License
61
71
 
62
72
  MIT © [Ben Drucker](http://bendrucker.me)