timezone-soft 1.5.1 → 1.6.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/LICENSE +21 -0
- package/README.md +141 -108
- package/builds/timezone-soft.cjs +967 -1047
- package/builds/timezone-soft.js +1025 -0
- package/builds/timezone-soft.min.js +2 -0
- package/package.json +58 -40
- package/types/index.d.cts +25 -0
- package/types/index.d.ts +14 -2
- package/builds/timezone-soft.min.cjs +0 -1
- package/builds/timezone-soft.mjs +0 -1099
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 spencer kelly
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,160 +1,193 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
|
|
3
|
-
<div>
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<img src="https://codecov.io/gh/spencermountain/timezone-soft/branch/master/graph/badge.svg" />
|
|
12
|
-
</a> -->
|
|
13
|
-
<a href="https://unpkg.com/timezone-soft/builds/timezone-soft.min.js">
|
|
14
|
-
<img src="https://badge-size.herokuapp.com/spencermountain/timezone-soft/master/builds/timezone-soft.min.js" />
|
|
15
|
-
</a>
|
|
16
|
-
</div>
|
|
17
|
-
<div align="center">
|
|
18
|
-
<code>npm install timezone-soft</code>
|
|
19
|
-
</div>
|
|
20
|
-
<sub>
|
|
21
|
-
by
|
|
22
|
-
<a href="https://spencermountain.github.io/">Spencer Kelly</a>
|
|
23
|
-
</sub>
|
|
24
|
-
<div align="center">
|
|
25
|
-
<sup><i>(formerly called 'spacetime-informal')</i></sup>
|
|
26
|
-
</div>
|
|
2
|
+
<img src="https://cloud.githubusercontent.com/assets/399657/23590290/ede73772-01aa-11e7-8915-181ef21027bc.png" />
|
|
3
|
+
<div>informal timezone lookup</div>
|
|
4
|
+
<a href="https://npmjs.org/package/timezone-soft">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/timezone-soft.svg?style=flat-square" />
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://bundlephobia.com/result?p=timezone-soft@latest">
|
|
8
|
+
<img src="https://badgen.net/bundlejs/min/timezone-soft" />
|
|
9
|
+
</a>
|
|
10
|
+
<div><code>npm install timezone-soft</code></div>
|
|
27
11
|
</div>
|
|
28
|
-
<p></p>
|
|
29
12
|
|
|
30
13
|
<!-- spacer -->
|
|
31
|
-
<img height="
|
|
14
|
+
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
|
|
32
15
|
|
|
33
16
|
```js
|
|
34
|
-
import
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/*[{
|
|
39
|
-
iana: 'America/Chicago',
|
|
40
|
-
standard: { name: 'Central Standard Time', abbrev: 'CST' },
|
|
41
|
-
daylight: { name: 'Central Daylight Time', abbrev: 'CDT' }
|
|
42
|
-
}
|
|
43
|
-
]*/
|
|
17
|
+
import tzSoft from 'timezone-soft'
|
|
18
|
+
|
|
19
|
+
const matches = tzSoft('milwaukee')
|
|
20
|
+
matches[0].iana // 'America/Chicago'
|
|
44
21
|
```
|
|
45
22
|
|
|
23
|
+
People are not often aware of timezone [IANA IDs](https://www.iana.org/time-zones), and tend to use informal schemes to refer to timezones - things like `'PST'`, `'eastern time'`, `'vancouver bc'`, and `'china'`.
|
|
24
|
+
|
|
25
|
+
These names have cultural overlap, and their meaning can depend on the date.
|
|
26
|
+
|
|
27
|
+
This library applies opinionated heuristics to help turn this user-input into ranked matching IANA candidates.
|
|
28
|
+
|
|
29
|
+
Originally built for [spacetime](https://github.com/spencermountain/spacetime),
|
|
30
|
+
and formerly called `timezone-soft-informal`. This is a compressed dictionary of lookup terms for timezone ids, and some basic ranking heuristics when >1 results.
|
|
31
|
+
|
|
46
32
|
<!-- spacer -->
|
|
47
33
|
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
<div align="center">
|
|
36
|
+
<img src="https://cloud.githubusercontent.com/assets/399657/23590290/ede73772-01aa-11e7-8915-181ef21027bc.png" />
|
|
37
|
+
</div>
|
|
52
38
|
|
|
53
|
-
|
|
39
|
+
### Usage
|
|
40
|
+
```js
|
|
41
|
+
const tzSoft = require('timezone-soft') //commonjs supported
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
43
|
+
tzSoft('EST')[0].iana // 'America/New_York'
|
|
44
|
+
tzSoft('central')[0].iana // 'America/Chicago'
|
|
45
|
+
tzSoft('venezuela')[0].iana // 'America/Caracas'
|
|
46
|
+
tzSoft('south east asia')[0].iana // 'Asia/Bangkok'
|
|
47
|
+
```
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
`tzSoft(input: string)`
|
|
61
50
|
|
|
62
|
-
|
|
51
|
+
This returns an array of matching timezone objects, ordered by preference. An empty or
|
|
52
|
+
unrecognized string returns `[]`
|
|
63
53
|
|
|
64
|
-
|
|
54
|
+
A match looks like this:
|
|
55
|
+
```js
|
|
56
|
+
{
|
|
57
|
+
name: 'Central Time',
|
|
58
|
+
iana: 'America/Chicago',
|
|
59
|
+
standard: {
|
|
60
|
+
name: 'Central Standard Time',
|
|
61
|
+
abbr: 'CST',
|
|
62
|
+
offset: -6
|
|
63
|
+
},
|
|
64
|
+
daylight: {
|
|
65
|
+
name: 'Central Daylight Time',
|
|
66
|
+
abbr: 'CDT',
|
|
67
|
+
offset: -5,
|
|
68
|
+
start: '2nd-sun-mar-2h',
|
|
69
|
+
end: '1st-sun-nov-2h'
|
|
70
|
+
},
|
|
71
|
+
long: '(UTC-06:00) Central Time (US & Canada)'
|
|
72
|
+
}
|
|
73
|
+
```
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
75
|
+
Offsets are hours east of UTC; negative values are west of UTC. `daylight` can be
|
|
76
|
+
`null`.
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
`start` and `end` values are descriptive rule strings.
|
|
70
79
|
|
|
71
|
-
'**_IST_**' is used to mean:
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
- '_Irish Stardard Time_'
|
|
75
|
-
- '_Israeli Stardard Time_'
|
|
81
|
+
## Ambiguous inputs
|
|
76
82
|
|
|
77
|
-
|
|
83
|
+
Abbreviations can describe several places. For example:
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
```js
|
|
86
|
+
soft('IST').map(zone => zone.iana)
|
|
87
|
+
// ['Asia/Kolkata', 'Europe/Dublin', 'Asia/Jerusalem', 'Asia/Colombo']
|
|
88
|
+
```
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
Explicit IANA IDs containing `/` are resolved case-insensitively through the pinned
|
|
91
|
+
IANA **2026d** Zone/Link table before informal matching. Unknown IDs are not guessed
|
|
92
|
+
from their city component. A recognized ID without bundled display metadata returns
|
|
93
|
+
`[]`. Curated non-IANA phrases containing `/` can still match registered aliases.
|
|
83
94
|
|
|
84
|
-
|
|
95
|
+
All returned IDs use that table's canonical targets. For example, `Europe/Kiev`
|
|
96
|
+
returns `Europe/Kyiv`, `Asia/Kashgar` returns `Asia/Urumqi` (UTC+6, distinct from
|
|
97
|
+
Shanghai's UTC+8), and `America/Yellowknife` returns `America/Edmonton`.
|
|
98
|
+
This policy uses the main IANA files plus `backward`, not the optional `backzone`
|
|
99
|
+
historical split. Ordinary abbreviations such as `EST` remain informal queries.
|
|
85
100
|
|
|
86
|
-
|
|
101
|
+
Alias matches are sorted by
|
|
102
|
+
the number of packed aliases associated with each zone, descending. Ties preserve
|
|
103
|
+
insertion order in the source data. Canonicalization then merges duplicate targets
|
|
104
|
+
while preserving their first occurrence. This is a heuristic, not a population ranking
|
|
105
|
+
or a confidence score; adding aliases can change the preferred result.
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
Show all candidates when ambiguity matters, or ask for a city or IANA ID. The
|
|
108
|
+
library does not use the user's location to choose a result. Regression fixtures
|
|
109
|
+
cover the ordering of `CST`, `IST`, and `BST`.
|
|
89
110
|
|
|
90
|
-
|
|
111
|
+
## UTC and GMT offsets
|
|
91
112
|
|
|
92
|
-
|
|
93
|
-
|
|
113
|
+
`UTC` (including lowercase or surrounding whitespace) resolves only to `Etc/UTC`,
|
|
114
|
+
with abbreviation `UTC` and name `Coordinated Universal Time`. The aliases `UCT`,
|
|
115
|
+
`universal`, `zulu`, and `coordinated universal time` resolve to the same record.
|
|
116
|
+
`GMT` resolves to `Etc/GMT`. Geographic aliases cannot outrank these inputs.
|
|
94
117
|
|
|
95
|
-
|
|
118
|
+
Whole-hour offsets from UTC-12 through UTC+14 are supported:
|
|
96
119
|
|
|
97
120
|
```js
|
|
98
|
-
|
|
121
|
+
soft('UTC+0')[0].iana // 'Etc/GMT'
|
|
122
|
+
soft('UTC+14')[0].iana // 'Etc/GMT-14'
|
|
123
|
+
soft('-5h')[0].iana // 'Etc/GMT+5'
|
|
124
|
+
```
|
|
99
125
|
|
|
100
|
-
|
|
101
|
-
|
|
126
|
+
Surrounding whitespace is accepted for offset inputs. `UTC-5` means five hours
|
|
127
|
+
behind UTC. For compatibility, `GMT+5` follows the reversed IANA `Etc/GMT+5`
|
|
128
|
+
convention; its numeric offset and `long` description use the normal UTC sign.
|
|
129
|
+
`Etc/GMT+13` and `Etc/GMT+14` return `[]` because they are not IANA IDs;
|
|
130
|
+
`Etc/GMT-13` and `Etc/GMT-14` remain valid.
|
|
102
131
|
|
|
103
|
-
|
|
104
|
-
|
|
132
|
+
Fractional offset strings such as `UTC+5:30` return `[]`: the IANA fixed-offset
|
|
133
|
+
`Etc/GMT` IDs have whole-hour precision. Use a named zone such as `Asia/Kolkata` or
|
|
134
|
+
`india` instead. See the [IANA definitions](https://data.iana.org/time-zones/tzdb/etcetera).
|
|
105
135
|
|
|
106
|
-
|
|
107
|
-
// 'America/Caracas'
|
|
136
|
+
## Dates and daylight saving time
|
|
108
137
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
138
|
+
This package finds timezone names and supplies curated display metadata. Its
|
|
139
|
+
bundled DST rules are approximate, are not versioned by year, and are not suitable
|
|
140
|
+
for calculating historical or future transitions. See the
|
|
141
|
+
[data notes](data/README.md) for the rule syntax and provenance limitations.
|
|
112
142
|
|
|
113
|
-
|
|
143
|
+
Use a date-aware timezone library to determine the applicable abbreviation at a
|
|
144
|
+
specific instant. For example, with [spacetime](https://github.com/spencermountain/timezone-soft):
|
|
114
145
|
|
|
115
146
|
```js
|
|
116
|
-
import
|
|
147
|
+
import spacetime from 'spacetime'
|
|
148
|
+
import tzSoft from 'timezone-soft'
|
|
149
|
+
|
|
150
|
+
const display = tzSoft('montreal')[0]
|
|
151
|
+
if (display) {
|
|
152
|
+
const now = spacetime.now(display.iana)
|
|
153
|
+
const info = now.isDST() && display.daylight ? display.daylight : display.standard
|
|
154
|
+
console.log(now.time() + ' ' + info.abbr)
|
|
155
|
+
}
|
|
117
156
|
```
|
|
118
157
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
---
|
|
158
|
+
The `standard` and `daylight` fields are conventional display categories, not
|
|
159
|
+
IANA's `tm_isdst` flags. In Dublin, `standard` means winter GMT (UTC+0, Greenwich
|
|
160
|
+
Mean Time), and `daylight` means summer IST (UTC+1, Irish Standard Time). IANA's
|
|
161
|
+
native model treats Irish summer as standard and winter as negative DST; this API
|
|
162
|
+
retains its existing winter/summer arrangement for compatibility. Do not select a
|
|
163
|
+
field using a raw IANA DST flag without reconciling those conventions.
|
|
126
164
|
|
|
127
|
-
|
|
128
|
-
|
|
165
|
+
The identifier table is versioned independently of display metadata. The returned
|
|
166
|
+
metadata is only as current as this package's curated data. Coverage includes
|
|
167
|
+
`America/Ciudad_Juarez` (Mountain time with US DST rules) and
|
|
168
|
+
`America/Coyhaique` (permanent UTC−3). Runtime coverage checks flag new missing
|
|
169
|
+
records.
|
|
129
170
|
|
|
130
|
-
### DST
|
|
131
171
|
|
|
132
|
-
|
|
133
|
-
You can reckon this pretty-easily with [spacetime](https://github.com/spencermountain/spacetime), like this:
|
|
172
|
+
## TypeScript
|
|
134
173
|
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
const soft = require('timezone-soft')
|
|
174
|
+
```ts
|
|
175
|
+
import tzSoft, { type DisplayFormat } from 'timezone-soft'
|
|
138
176
|
|
|
139
|
-
|
|
140
|
-
|
|
177
|
+
const matches: DisplayFormat[] = tzSoft('montreal')
|
|
178
|
+
const zone = matches[0]
|
|
141
179
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
180
|
+
if (zone) {
|
|
181
|
+
console.log(zone.iana) // 'America/Toronto'
|
|
182
|
+
console.log(zone.standard.abbr) // 'EST'
|
|
183
|
+
console.log(zone.daylight?.abbr) // 'EDT'; undefined for zones without DST
|
|
184
|
+
} else {
|
|
185
|
+
console.log('No matching timezone')
|
|
146
186
|
}
|
|
147
|
-
console.log(s.time() + ' ' + show)
|
|
148
|
-
// '4:20pm EDT'
|
|
149
187
|
```
|
|
150
188
|
|
|
151
|
-
<!-- spacer -->
|
|
152
|
-
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
|
|
153
|
-
|
|
154
|
-
work-in-progress!
|
|
155
|
-
|
|
156
189
|
### See also
|
|
157
190
|
|
|
158
|
-
- [TimeZoneNames](https://github.com/mattjohnsonpint/TimeZoneNames) .NET
|
|
191
|
+
- [TimeZoneNames](https://github.com/mattjohnsonpint/TimeZoneNames) for .NET.
|
|
159
192
|
|
|
160
|
-
MIT
|
|
193
|
+
MIT, PRs welcome
|