Skip to content

Commit 7798c35

Browse files
chore: release 0.0.17
* feat: adds support for parsing time zone offsets in the format [+-]HH:mm (#39) * Add support for parsing time zone offsets in the format [+-]HH:mm * Fix ISO 8601 regex to support colons in timezone offsets. * test: tweaks date test * docs: adds size ref to intro --------- Co-authored-by: Kouta Motegi <motegi@sansan.com>
1 parent 7e046a6 commit 7798c35

File tree

9 files changed

+44
-12
lines changed

9 files changed

+44
-12
lines changed

.size-limit.cjs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ module.exports = [
1414

1515
{ path, limit: "2.9 kb", import: "{ format }", name: "format" },
1616
{ path, limit: "4.3 kb", import: "{ parse }", name: "parse" },
17-
{ path, limit: "5.1 kb", import: "*", name: "all esm" },
18-
{ path: "./dist/index.cjs", limit: "5.4 kb", import: "*", name: "all cjs" },
17+
{ path, limit: "5.2 kb", import: "*", name: "all esm" },
18+
{ path: "./dist/index.cjs", limit: "5.5 kb", import: "*", name: "all cjs" },
1919
]

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Tempo is a new library in a proud tradition of JavaScript date and time librarie
1010

1111
Tempo is best thought of as a collection of utilities for working with `Date` objects — an important distinction from other libraries that provide custom date primitives. Under the hood, Tempo mines JavaScript's `Intl.DateTimeFormat` to extract complex data like timezones offsets and locale aware date formats giving you a simple API to format, parse, and manipulates dates.
1212

13-
Tempo is tiny tree-shakable framework, you can only take what you need. All functionality is available in **5.1 kB for esm** and **5.4 kB for cjs** modules (minified and brotlied). [Size Limit](https://github.com/ai/size-limit) controls the size.
13+
Tempo is tiny tree-shakable framework, you can only take what you need. All functionality is available in **5.2 kB for esm** and **5.5 kB for cjs** modules (minified and brotlied). [Size Limit](https://github.com/ai/size-limit) controls the size.
1414

1515
<a href="https://tempo.formkit.com">
1616
<img src="docs/public/read-the-docs.png" alt="Read the docs" width="200" height="43">

docs/components/content/Introduction.vue

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66
<p>
77
Tempo is a new library in a proud tradition of JavaScript date and time
88
libraries. Inspired by the likes of moment.js, day.js, and date-fns, Tempo
9-
is built from the ground up to be as small and easy to use as possible —
10-
including first-class support for timezone operations.
9+
is built from the ground up to be as small and easy to use as possible
10+
(all features ~5kB compressed) — including first-class support for
11+
timezone operations.
1112
</p>
1213
<p>
1314
Tempo is best thought of as a collection of utilities for working with the
1415
native <code>Date</code> object — an important distinction from other
1516
libraries that provide custom date primitives. Under the hood, Tempo mines
1617
JavaScript's <code>Intl.DateTimeFormat</code> to extract complex data like
17-
timezones offsets and locale aware date formats, giving you a simple API to
18-
format, parse, and manipulate dates.
18+
timezones offsets and locale aware date formats, giving you a simple API
19+
to format, parse, and manipulate dates.
1920
</p>
2021

2122
<CodeExample file="introduction" />

src/__tests__/date.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@ describe("date", () => {
1212
expect(date("2022-01-22T00:00-0300").toISOString()).toBe(
1313
"2022-01-22T03:00:00.000Z"
1414
)
15+
expect(date("2022-01-22T00:00-03:24").toISOString()).toBe(
16+
"2022-01-22T03:24:00.000Z"
17+
)
1518
})
1619
})

src/__tests__/parse.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ describe("parse", () => {
8484
}:22:00.000Z`
8585
)
8686
})
87+
it("can parse [+-]HH:mm", () => {
88+
expect(
89+
parse("1994-06-22T04:22:32+09:00", "YYYY-MM-DDTHH:mm:ssZ").toISOString()
90+
).toBe("1994-06-21T19:22:32.000Z")
91+
expect(
92+
parse("1994-06-22T04:22:32+09:00").toISOString()
93+
).toBe("1994-06-21T19:22:32.000Z")
94+
})
8795
it("can parse the string month in en", () => {
8896
let h: number | string = new Date("2019-01-01").getTimezoneOffset() / 60
8997
h = h < 10 ? `0${h}` : h

src/__tests__/validOffset.spec.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ describe("validOffset", () => {
66
it("returns its own value when valid", () => {
77
expect(validOffset("+0000")).toBe("+0000")
88
expect(validOffset("+0100")).toBe("+0100")
9+
expect(validOffset("+00:00")).toBe("+00:00")
10+
expect(validOffset("+01:00")).toBe("+01:00")
911
})
1012
})

src/common.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,23 @@ export const fixedLength = {
7171
hh: 2,
7272
mm: 2,
7373
ss: 2,
74-
Z: 5,
74+
}
75+
76+
/**
77+
* token Z can have variable length depending on the actual value, so it's
78+
*/
79+
export function fixedLengthByOffset(offsetString: string): number {
80+
// starts with [+-]xx:xx
81+
if (/^[+-]\d{2}:\d{2}/.test(offsetString)) {
82+
return 6
83+
}
84+
85+
// starts with [+-]xxxx
86+
if (/^[+-]\d{4}/.test(offsetString)) {
87+
return 5
88+
}
89+
90+
throw new Error("Invalid offset format")
7591
}
7692

7793
/**
@@ -297,11 +313,11 @@ export function offsetToMins(offset: string): number {
297313

298314
/**
299315
* Validates that an offset is valid according to the format:
300-
* [+-]HHmm
316+
* [+-]HHmm or [+-]HH:mm
301317
* @param offset - The offset to validate.
302318
*/
303319
export function validOffset(offset: string) {
304-
const valid = /^([+-])[0-3][0-9][0-6][0-9]$/.test(offset)
320+
const valid = /^([+-])[0-3][0-9]:?[0-6][0-9]$/.test(offset)
305321
if (!valid) throw new Error(`Invalid offset: ${offset}`)
306322
return offset
307323
}

src/iso8601.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* specificity.
55
*/
66
export const iso8601Match =
7-
/^([0-9]{4})-([0-1][0-9])(?:-([0-3][0-9]))?(?:[T ]?([0-2][0-9])(?::([0-5][0-9]))?(?::([0-5][0-9]))?)?(?:\.[0-9]+)?(Z|(?:\+|\-)[0-9]{4})?$/
7+
/^([0-9]{4})-([0-1][0-9])(?:-([0-3][0-9]))?(?:[T ]?([0-2][0-9])(?::([0-5][0-9]))?(?::([0-5][0-9]))?)?(?:\.[0-9]+)?(Z|(?:\+|\-)[0-9]{2}:?[0-9]{2})?$/
88

99
/**
1010
* True when the date string is valid ISO 8601.

src/parse.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { date } from "./date"
2-
import { validate, styles, fixedLength, four, two, validOffset } from "./common"
2+
import { validate, styles, fixedLength, four, two, validOffset, fixedLengthByOffset } from "./common"
33
import { formatStr } from "./formatStr"
44
import { fourDigitYear } from "./fourDigitYear"
55
import { ap } from "./ap"
@@ -172,6 +172,8 @@ export function parseParts(dateStr: string, formatParts: Part[]): FilledPart[] {
172172
if (current.partName === "literal") {
173173
// Literals can be discarded
174174
len = current.partValue.length
175+
} else if (current.partName === "timeZoneName") {
176+
len = fixedLengthByOffset(dateStr.substring(pos))
175177
} else if (current.token in fixedLength) {
176178
// Fixed length parse
177179
len = fixedLength[current.token as keyof typeof fixedLength]

0 commit comments

Comments
 (0)