Skip to content

Commit 9671eca

Browse files
feat: add millisecond support to format, parse, and helpers
1 parent 6791ab7 commit 9671eca

30 files changed

+1010
-1591
lines changed

docs/components/content/Format.vue

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ import sizes from "../../assets/func-sizes.json"
368368
<td>07, 17</td>
369369
<td>The second 00-59</td>
370370
</tr>
371+
<tr>
372+
<td><code>SSS</code></td>
373+
<td>007, 123, 789</td>
374+
<td>The millisecond, 3 digits (000-999). When parsing, accepts variable-length fractional seconds (1-9 digits).</td>
375+
</tr>
371376
<tr>
372377
<td><code>a</code></td>
373378
<td>{{ format(new Date(), "a") }}</td>
@@ -391,6 +396,14 @@ import sizes from "../../assets/func-sizes.json"
391396
</tbody>
392397
</table>
393398
<CodeExample file="format-tokens" />
399+
<h3 id="milliseconds">Milliseconds</h3>
400+
<p>
401+
The <code>SSS</code> token formats milliseconds as 3 digits (000-999).
402+
When parsing, it graciously accepts variable-length fractional seconds
403+
(1-9 digits), making it compatible with high-precision timestamps like
404+
those from databases or APIs.
405+
</p>
406+
<CodeExample file="milliseconds" />
394407
<h3 id="format-options">Format options</h3>
395408
<p>
396409
The <code>format()</code> function can accept an object of options as its

docs/components/content/Helpers.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,21 @@ const fns: Record<
209209
],
210210
example: "isEqual",
211211
},
212+
sameMillisecond: {
213+
description:
214+
"Checks if two dates have the same millisecond value (0-999). This compares only the millisecond component, ignoring the rest of the timestamp.",
215+
arguments: [
216+
{
217+
name: "dateA",
218+
type: "Date",
219+
},
220+
{
221+
name: "dateB",
222+
type: "Date",
223+
},
224+
],
225+
return: "boolean",
226+
},
212227
sameSecond: {
213228
description:
214229
"Checks if two dates are the same second. This function is useful for comparing dates but ignoring the milliseconds.",

docs/components/content/Modify.vue

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ const fns: Record<
6262
},
6363
],
6464
},
65+
addMillisecond: {
66+
name: "add-millisecond",
67+
description:
68+
"Returns a new Date object with a positive or negative number of milliseconds applied to date argument. To subtract milliseconds, use a negative number.",
69+
return: "Date",
70+
arguments: [
71+
{
72+
name: "date",
73+
type: "string | Date",
74+
},
75+
{
76+
name: "amount",
77+
type: "number",
78+
},
79+
],
80+
},
6581
addMonth: {
6682
name: "add-month",
6783
description: `Returns a new Date object with a positive or negative number of

docs/examples/format-tokens.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ format(t, "h:mm:ss A Z", l)
3535
format(t, "YY/MM/DD", l)
3636
format(t, "YYYY MMMM D", l)
3737
format(t, "M-D-YY", l)
38+
format(t, "HH:mm:ss.SSS", l)
39+
format(t, "YYYY-MM-DDTHH:mm:ss.SSSZ", l)

docs/examples/milliseconds.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { format, parse } from "@formkit/tempo"
2+
3+
// Format with milliseconds using SSS token
4+
const d = new Date("2024-01-15T10:30:45.789Z")
5+
format({ date: d, format: "HH:mm:ss.SSS", tz: "UTC" })
6+
format({ date: d, format: "YYYY-MM-DDTHH:mm:ss.SSSZ", tz: "UTC" })
7+
8+
// SSS always outputs 3 digits, padding with zeros
9+
const d2 = new Date("2024-01-15T10:30:45.007Z")
10+
format({ date: d2, format: "ss.SSS", tz: "UTC" })
11+
12+
// Parse milliseconds - SSS accepts variable-length input
13+
parse("10:30:45.789", "HH:mm:ss.SSS")
14+
// 1 digit -> 700ms
15+
parse("10:30:45.7", "HH:mm:ss.SSS")
16+
// 2 digits -> 780ms
17+
parse("10:30:45.78", "HH:mm:ss.SSS")
18+
// 6 digits -> 123ms (truncates to ms)
19+
parse("10:30:45.123456", "HH:mm:ss.SSS")

docs/nuxt.config.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,20 @@ export default defineNuxtConfig({
9797
worker: {
9898
format: "es",
9999
},
100+
optimizeDeps: {
101+
exclude: ["@formkit/tempo"],
102+
},
100103
},
101104
nitro: {
102105
storage: {
103-
kv: {
104-
driver: process.env.KV_DRIVER,
105-
accountId: process.env.KV_ACCOUNT_ID,
106-
namespaceId: process.env.KV_NAMESPACE_ID,
107-
apiToken: process.env.KV_API_TOKEN,
108-
},
106+
kv: process.env.KV_DRIVER
107+
? {
108+
driver: process.env.KV_DRIVER,
109+
accountId: process.env.KV_ACCOUNT_ID,
110+
namespaceId: process.env.KV_NAMESPACE_ID,
111+
apiToken: process.env.KV_API_TOKEN,
112+
}
113+
: { driver: "memory" },
109114
},
110115
},
111116
})

docs/package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@
1111
},
1212
"devDependencies": {
1313
"@nuxt/devtools": "latest",
14-
"@nuxtjs/color-mode": "^3.3.2",
15-
"@nuxtjs/tailwindcss": "^6.11.2",
16-
"@types/node": "^18.17.0",
17-
"@vueuse/core": "^10.7.2",
18-
"@vueuse/nuxt": "^10.7.2",
19-
"nuxt": "^3.10.0",
20-
"nuxt-fathom": "^0.0.1",
21-
"vitest": "^1.2.2"
14+
"@nuxtjs/color-mode": "^4.0.0",
15+
"@nuxtjs/tailwindcss": "^6.14.0",
16+
"@types/node": "^25.0.3",
17+
"@vueuse/core": "^14.1.0",
18+
"@vueuse/nuxt": "^14.1.0",
19+
"nuxt": "^4.2.2",
20+
"nuxt-fathom": "^0.0.3",
21+
"vitest": "^4.0.16"
2222
},
2323
"dependencies": {
24-
"@docsearch/js": "3",
25-
"@formkit/auto-animate": "^0.8.1",
24+
"@docsearch/js": "^4.3.2",
25+
"@formkit/auto-animate": "^0.9.0",
2626
"@formkit/tempo": "workspace:*",
27-
"monaco-editor": "^0.40.0"
27+
"monaco-editor": "^0.55.1"
2828
}
2929
}

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,17 @@
5555
"author": "Justin Schroeder <justin@formkit.com>",
5656
"license": "MIT",
5757
"devDependencies": {
58-
"@size-limit/esbuild": "^11.1.1",
59-
"@size-limit/file": "^11.1.1",
60-
"@size-limit/preset-small-lib": "^11.0.2",
61-
"@types/node": "^20.11.10",
62-
"bumpp": "^9.3.0",
58+
"@size-limit/esbuild": "^12.0.0",
59+
"@size-limit/file": "^12.0.0",
60+
"@size-limit/preset-small-lib": "^12.0.0",
61+
"@types/node": "^25.0.3",
62+
"bumpp": "^10.3.2",
6363
"bytes-iec": "^3.1.1",
64-
"esbuild-plugin-file-path-extensions": "^2.0.0",
65-
"publint": "^0.2.7",
66-
"size-limit": "^11.0.2",
67-
"tsup": "^8.0.1",
68-
"typescript": "^5.3.3",
69-
"vitest": "^1.2.1"
64+
"esbuild-plugin-file-path-extensions": "^2.1.4",
65+
"publint": "^0.3.16",
66+
"size-limit": "^12.0.0",
67+
"tsup": "^8.5.1",
68+
"typescript": "^5.9.3",
69+
"vitest": "^4.0.16"
7070
}
7171
}

0 commit comments

Comments
 (0)