datetime-lube 1.0.0 → 1.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Fixed
6
+
7
+ - `startOf` returned a day, week, month or year that began exactly where a forward jump of the clock
8
+ lands 1 ms late.
9
+ - `stringToDate("-000000-01-01")` returned year 0 instead of an invalid `Date`, which ISO 8601 and
10
+ ECMAScript give `-000000`; it is invalid with and without a time zone.
11
+
3
12
  ## 1.0.0
4
13
 
5
14
  ### Breaking
package/package.json CHANGED
@@ -4,9 +4,6 @@
4
4
  "url": "https://github.com/artxe/lube-series/issues"
5
5
  },
6
6
  "description": "Simplify Date Manipulation with Time Zones in JavaScript",
7
- "devDependencies": {
8
- "@typescript/native": "npm:typescript@^7.0.2"
9
- },
10
7
  "engines": {
11
8
  "node": ">=18"
12
9
  },
@@ -55,10 +52,10 @@
55
52
  ]
56
53
  }
57
54
  },
58
- "version": "1.0.0",
55
+ "version": "1.0.1",
59
56
  "scripts": {
60
57
  "dts": "node ../../scripts/tsc_with_clean.js datetime-lube",
61
58
  "lint": "pnpm -w lint",
62
- "test": "pnpm -w exec vitest run --coverage test/datetime-lube"
59
+ "test": "pnpm -w exec vitest run test/datetime-lube"
63
60
  }
64
61
  }
package/src/add.js CHANGED
@@ -51,19 +51,30 @@ function add_months(date, months, zone) {
51
51
  */
52
52
  function compile(sum) {
53
53
  let steps = durations.get(sum)
54
- if (steps) return steps
54
+ if (steps) {
55
+ return steps
56
+ }
55
57
  steps = []
56
58
  if (!/\S/.test(sum) || /\S/.test(
57
59
  sum.replace(duration_regex, "")
58
- )) throw new RangeError(
59
- `add: Invalid duration "${String(sum)}"`
60
- )
60
+ )) {
61
+ throw new RangeError(
62
+ `add: Invalid duration "${String(sum)}"`
63
+ )
64
+ }
61
65
  for (const [ , value = "", unit = "" ] of sum.matchAll(duration_regex)) {
62
- if (!+value) continue
63
- if (unit == "W") steps.push("D", +value * 7)
64
- else steps.push(unit, +value)
66
+ if (!+value) {
67
+ continue
68
+ }
69
+ if (unit == "W") {
70
+ steps.push("D", +value * 7)
71
+ } else {
72
+ steps.push(unit, +value)
73
+ }
74
+ }
75
+ if (durations.size >= 1000) {
76
+ durations.clear()
65
77
  }
66
- if (durations.size >= 1000) durations.clear()
67
78
  durations.set(sum, steps)
68
79
  return steps
69
80
  }
@@ -104,22 +115,28 @@ export default function(date, sum, zone) {
104
115
  const steps = compile(sum)
105
116
  check_zone("add", zone)
106
117
  const result = new Date(time)
107
- if (isNaN(time)) return result
118
+ if (isNaN(time)) {
119
+ return result
120
+ }
108
121
  if (zone === undefined) {
109
122
  for (let i = 0; i < steps.length; i += 2) {
110
123
  const unit = /** @type {string} */(steps[i])/**/
111
124
  const value = /** @type {number} */(steps[i + 1])/**/
112
125
  const ms = unit_ms[unit]
113
- if (ms) result.setTime(result.getTime() + value * ms)
114
- else if (unit == "D") result.setDate(result.getDate() + value)
115
- else result.setTime(
116
- add_months(
117
- result,
118
- unit == "Y"
119
- ? value * 12
120
- : value
121
- ).getTime()
122
- )
126
+ if (ms) {
127
+ result.setTime(result.getTime() + value * ms)
128
+ } else if (unit == "D") {
129
+ result.setDate(result.getDate() + value)
130
+ } else {
131
+ result.setTime(
132
+ add_months(
133
+ result,
134
+ unit == "Y"
135
+ ? value * 12
136
+ : value
137
+ ).getTime()
138
+ )
139
+ }
123
140
  }
124
141
  return result
125
142
  }
package/src/calendar.js CHANGED
@@ -10,7 +10,9 @@ function days_of(year, month, day) {
10
10
  year += Math.floor(month / 12)
11
11
  month = (month % 12 + 12) % 12
12
12
  }
13
- if (month < 2) year--
13
+ if (month < 2) {
14
+ year--
15
+ }
14
16
  const era = Math.floor(year / 400)
15
17
  const yoe = year - era * 400
16
18
  return era * 146097
@@ -20,18 +20,26 @@ const tokens = {
20
20
  */
21
21
  function compile(format) {
22
22
  let parts = formats.get(format)
23
- if (parts) return parts
23
+ if (parts) {
24
+ return parts
25
+ }
24
26
  parts = []
25
27
  let last = 0
26
28
  for (const { 0: token, index = 0 } of format.matchAll(token_regex)) {
27
- if (index > last) parts.push(format.slice(last, index))
29
+ if (index > last) {
30
+ parts.push(format.slice(last, index))
31
+ }
28
32
  parts.push(
29
33
  /** @type {number[]} */(tokens[token])/**/
30
34
  )
31
35
  last = index + token.length
32
36
  }
33
- if (last < format.length) parts.push(format.slice(last))
34
- if (formats.size >= 1000) formats.clear()
37
+ if (last < format.length) {
38
+ parts.push(format.slice(last))
39
+ }
40
+ if (formats.size >= 1000) {
41
+ formats.clear()
42
+ }
35
43
  formats.set(format, parts)
36
44
  return parts
37
45
  }
@@ -86,7 +94,9 @@ export default function(
86
94
  ) {
87
95
  const time = time_of("dateToString", date)
88
96
  check_zone("dateToString", zone)
89
- if (isNaN(time)) return "Invalid Date"
97
+ if (isNaN(time)) {
98
+ return "Invalid Date"
99
+ }
90
100
  const fields = fields_of(date, zone)
91
101
  const parts = compile(format)
92
102
  let result = ""
@@ -98,7 +108,7 @@ export default function(
98
108
  /** @type {number} */(fields[0])/**/
99
109
  )
100
110
  : pad(
101
- /** @type {number} */(fields[/** @type {number} */(part[0])/**/])/**/ + /** @type {number} */(part[2])/**/,
111
+ /** @type {number} */(fields[/** @type {number} */(part[0])/**/])/**/ + /** @type {number} */(part[2])/**/,
102
112
  /** @type {number} */(part[1])/**/
103
113
  )
104
114
  }
package/src/diff.js CHANGED
@@ -42,7 +42,9 @@ function anchor_after(
42
42
  /** @type {number} */(from_fields[6])/**/
43
43
  ]
44
44
  const distance = wall_of_fields(fields) - to_wall
45
- if (Math.abs(distance) >= 172800000) return distance
45
+ if (Math.abs(distance) >= 172800000) {
46
+ return distance
47
+ }
46
48
  const time = date_of(fields, zone).getTime()
47
49
  return isNaN(time)
48
50
  ? distance
@@ -71,13 +73,19 @@ function anchor_after(
71
73
  export default function(from, to, unit, zone) {
72
74
  const start = time_of("diff", from)
73
75
  const end = time_of("diff", to)
74
- if (!units_of.has(unit)) throw new RangeError(
75
- `diff: Invalid unit "${String(unit)}"`
76
- )
76
+ if (!units_of.has(unit)) {
77
+ throw new RangeError(
78
+ `diff: Invalid unit "${String(unit)}"`
79
+ )
80
+ }
77
81
  check_zone("diff", zone)
78
- if (isNaN(start) || isNaN(end)) return NaN
82
+ if (isNaN(start) || isNaN(end)) {
83
+ return NaN
84
+ }
79
85
  const ms = unit_ms[unit]
80
- if (ms) return Math.trunc((end - start) / ms) + 0
86
+ if (ms) {
87
+ return Math.trunc((end - start) / ms) + 0
88
+ }
81
89
  const from_fields = fields_of(from, zone)
82
90
  const to_fields = fields_of(to, zone)
83
91
  if (unit == "D" || unit == "W") {
@@ -99,8 +107,11 @@ export default function(from, to, unit, zone) {
99
107
  const to_day = /** @type {number} */(to_fields[2])/**/
100
108
  const from_day = /** @type {number} */(from_fields[2])/**/
101
109
  if (Math.abs(to_day - from_day) > 2 && to_day < 27 && from_day < 27) {
102
- if (months > 0 && to_day < from_day) months--
103
- else if (months < 0 && to_day > from_day) months++
110
+ if (months > 0 && to_day < from_day) {
111
+ months--
112
+ } else if (months < 0 && to_day > from_day) {
113
+ months++
114
+ }
104
115
  } else {
105
116
  const to_wall = wall_of_fields(to_fields)
106
117
  if (end >= start) {
@@ -111,14 +122,18 @@ export default function(from, to, unit, zone) {
111
122
  to_wall,
112
123
  end,
113
124
  zone
114
- ) > 0) months--
125
+ ) > 0) {
126
+ months--
127
+ }
115
128
  if (anchor_after(
116
129
  from_fields,
117
130
  months + 1,
118
131
  to_wall,
119
132
  end,
120
133
  zone
121
- ) <= 0) months++
134
+ ) <= 0) {
135
+ months++
136
+ }
122
137
  } else {
123
138
  months = Math.min(months, 0)
124
139
  while (months && anchor_after(
@@ -127,14 +142,18 @@ export default function(from, to, unit, zone) {
127
142
  to_wall,
128
143
  end,
129
144
  zone
130
- ) < 0) months++
145
+ ) < 0) {
146
+ months++
147
+ }
131
148
  if (anchor_after(
132
149
  from_fields,
133
150
  months - 1,
134
151
  to_wall,
135
152
  end,
136
153
  zone
137
- ) >= 0) months--
154
+ ) >= 0) {
155
+ months--
156
+ }
138
157
  }
139
158
  }
140
159
  return unit == "Y"
package/src/end_of.js CHANGED
@@ -40,11 +40,15 @@ const units_of = new Set(
40
40
  */
41
41
  export default function(date, unit, zone) {
42
42
  const time = time_of("endOf", date)
43
- if (!units_of.has(unit)) throw new RangeError(
44
- `endOf: Invalid unit "${String(unit)}"`
45
- )
43
+ if (!units_of.has(unit)) {
44
+ throw new RangeError(
45
+ `endOf: Invalid unit "${String(unit)}"`
46
+ )
47
+ }
46
48
  check_zone("endOf", zone)
47
- if (isNaN(time)) return new Date(NaN)
49
+ if (isNaN(time)) {
50
+ return new Date(NaN)
51
+ }
48
52
  const ms = unit_ms[unit]
49
53
  if (ms) {
50
54
  if (zone !== undefined) {
@@ -66,8 +70,10 @@ export default function(date, unit, zone) {
66
70
  const result = new Date(time + rest - 1)
67
71
  if (
68
72
  result.getTimezoneOffset() == date.getTimezoneOffset()
69
- && result.getSeconds() == (ms > 1000 ? 59 : date.getSeconds())
70
- ) return result
73
+ && result.getSeconds() == (ms > 1000 ? 59 : date.getSeconds())
74
+ ) {
75
+ return result
76
+ }
71
77
  result.setTime(unit_end(time, ms))
72
78
  return result
73
79
  }
@@ -102,16 +108,23 @@ export default function(date, unit, zone) {
102
108
  }
103
109
  const offset = offset_in(time, zone)
104
110
  const fields = fields_of_wall(time + offset)
105
- if (unit == "W") fields[2] = /** @type {number} */(fields[2])/**/ + 7 - (/** @type {number} */(fields[7])/**/ + 6) % 7
106
- else fields[from - 1] = /** @type {number} */(fields[from - 1])/**/ + 1
107
- for (let i = from; i < 7; i++) fields[i] = i == 2 ? 1 : 0
111
+ if (unit == "W") {
112
+ fields[2] = /** @type {number} */(fields[2])/**/ + 7 - (/** @type {number} */(fields[7])/**/ + 6) % 7
113
+ } else {
114
+ fields[from - 1] = /** @type {number} */(fields[from - 1])/**/ + 1
115
+ }
116
+ for (let i = from; i < 7; i++) {
117
+ fields[i] = i == 2 ? 1 : 0
118
+ }
108
119
  const wall = wall_of_fields(fields)
109
120
  if (zone !== undefined) {
110
121
  const next = offset_of(wall - offset, zone)
111
122
  if (
112
123
  next == offset
113
- || wall - next > time && offset_of(wall - next, zone) == next
114
- ) return new Date(wall - next - 1)
124
+ || wall - next > time && offset_of(wall - next, zone) == next
125
+ ) {
126
+ return new Date(wall - next - 1)
127
+ }
115
128
  end = instant_of(wall, zone) - 1
116
129
  }
117
130
  return new Date(end_at(wall, end, time, zone))
package/src/start_of.js CHANGED
@@ -36,11 +36,15 @@ const units_of = new Set(
36
36
  */
37
37
  export default function(date, unit, zone) {
38
38
  const time = time_of("startOf", date)
39
- if (!units_of.has(unit)) throw new RangeError(
40
- `startOf: Invalid unit "${String(unit)}"`
41
- )
39
+ if (!units_of.has(unit)) {
40
+ throw new RangeError(
41
+ `startOf: Invalid unit "${String(unit)}"`
42
+ )
43
+ }
42
44
  check_zone("startOf", zone)
43
- if (isNaN(time)) return new Date(NaN)
45
+ if (isNaN(time)) {
46
+ return new Date(NaN)
47
+ }
44
48
  const ms = unit_ms[unit]
45
49
  if (ms) {
46
50
  if (zone !== undefined) {
@@ -60,8 +64,10 @@ export default function(date, unit, zone) {
60
64
  const result = new Date(time - rest)
61
65
  if (
62
66
  result.getTimezoneOffset() == date.getTimezoneOffset()
63
- && result.getSeconds() == (ms > 1000 ? 0 : date.getSeconds())
64
- ) return result
67
+ && result.getSeconds() == (ms > 1000 ? 0 : date.getSeconds())
68
+ ) {
69
+ return result
70
+ }
65
71
  result.setTime(unit_start(time, ms))
66
72
  return result
67
73
  }
@@ -84,15 +90,23 @@ export default function(date, unit, zone) {
84
90
  0,
85
91
  0
86
92
  )
87
- if (result.getTime() <= time && !(result.getHours() || result.getMinutes() || result.getSeconds())) return result
93
+ if (result.getTime() <= time && !(result.getHours() || result.getMinutes() || result.getSeconds())) {
94
+ return result
95
+ }
88
96
  }
89
97
  const fields = fields_of(date, zone)
90
- if (unit == "W") fields[2] = /** @type {number} */(fields[2])/**/ - (/** @type {number} */(fields[7])/**/ + 6) % 7
91
- for (let i = from; i < 7; i++) fields[i] = i == 2 ? 1 : 0
98
+ if (unit == "W") {
99
+ fields[2] = /** @type {number} */(fields[2])/**/ - (/** @type {number} */(fields[7])/**/ + 6) % 7
100
+ }
101
+ for (let i = from; i < 7; i++) {
102
+ fields[i] = i == 2 ? 1 : 0
103
+ }
92
104
  const wall = wall_of_fields(fields)
93
105
  if (zone !== undefined) {
94
106
  const start = instant_of(wall, zone, true)
95
- if (start <= time) return new Date(start)
107
+ if (start <= time) {
108
+ return new Date(start)
109
+ }
96
110
  }
97
111
  const before = offset_in(wall - 86400000, zone)
98
112
  const guess = wall - before
@@ -100,10 +114,12 @@ export default function(date, unit, zone) {
100
114
  const earliest = after == before
101
115
  ? wall - offset_in(time, zone)
102
116
  : wall - after
103
- if (!(earliest >= -8.64e15)) return new Date(NaN)
117
+ if (!(earliest >= -8.64e15)) {
118
+ return new Date(NaN)
119
+ }
104
120
  return new Date(
105
121
  transition_of(
106
- earliest,
122
+ earliest - 1,
107
123
  after == before || guess > time
108
124
  ? time
109
125
  : guess,
@@ -22,22 +22,30 @@ const zone_regex = /(?<![a-z])(?:[cemp][ds]t|gmt|utc?|z)(?![a-z])|(?:\s|[ap]m|\d
22
22
  */
23
23
  function compile(format) {
24
24
  let parts = formats.get(format)
25
- if (parts) return parts
25
+ if (parts) {
26
+ return parts
27
+ }
26
28
  parts = []
27
29
  let last = 0
28
30
  for (const { 0: token, index = 0 } of format.matchAll(token_regex)) {
29
- if (index > last) parts.push(
30
- [ ...format.slice(last, index) ].length
31
- )
31
+ if (index > last) {
32
+ parts.push(
33
+ [ ...format.slice(last, index) ].length
34
+ )
35
+ }
32
36
  parts.push(
33
37
  /** @type {number[]} */(tokens[token])/**/
34
38
  )
35
39
  last = index + token.length
36
40
  }
37
- if (last < format.length) parts.push(
38
- [ ...format.slice(last) ].length
39
- )
40
- if (formats.size >= 1000) formats.clear()
41
+ if (last < format.length) {
42
+ parts.push(
43
+ [ ...format.slice(last) ].length
44
+ )
45
+ }
46
+ if (formats.size >= 1000) {
47
+ formats.clear()
48
+ }
41
49
  formats.set(format, parts)
42
50
  return parts
43
51
  }
@@ -47,9 +55,14 @@ function compile(format) {
47
55
  */
48
56
  function out_of_range(match) {
49
57
  const [ , year, month, day, hour, minute, second ] = match
50
- if (month === undefined) return false
58
+ if (month === undefined) {
59
+ return false
60
+ }
51
61
  const index = +month - 1
52
- return index < 0 || index > 11 || day !== undefined && (+day < 1 || +day > last_day(+(year ?? 0), index)) || +(hour ?? 0) > (+(minute ?? 0) || +(second ?? 0) || +(match[7] ?? 0)
62
+ return index < 0 || index > 11 || day !== undefined && (+day < 1 || +day > last_day(
63
+ +/** @type {string} */(year)/**/,
64
+ index
65
+ )) || +(hour ?? 0) > (+(minute ?? 0) || +(second ?? 0) || +(match[7] ?? 0)
53
66
  ? 23
54
67
  : 24) || +(minute ?? 0) > 59 || +(second ?? 0) > 59
55
68
  }
@@ -88,26 +101,39 @@ function out_of_range(match) {
88
101
  * @example stringToDate("2024-07-15 09:00", "YYYY-MM-DD HH:mm", "Asia/Seoul")
89
102
  */
90
103
  export default function(date, format, zone) {
91
- if (typeof date != "string") throw new TypeError(
92
- `stringToDate: Expected a string, got ${date === null ? "null" : typeof date}`
93
- )
104
+ if (typeof date != "string") {
105
+ throw new TypeError(
106
+ `stringToDate: Expected a string, got ${date === null ? "null" : typeof date}`
107
+ )
108
+ }
94
109
  check_zone("stringToDate", zone)
95
110
  if (format === undefined) {
96
111
  const native = new Date(date)
97
112
  const valid = !isNaN(native.getTime())
98
- if (!valid && zone === undefined) return native
113
+ if (!valid && zone === undefined) {
114
+ return native
115
+ }
99
116
  const match = iso_regex.exec(date)
100
- if (match && out_of_range(match)) return new Date(NaN)
117
+ if (match && out_of_range(match)) {
118
+ return new Date(NaN)
119
+ }
101
120
  const parsed = match?.[8] === ""
102
121
  ? match
103
122
  : null
104
123
  if (parsed) {
105
- if (zone === undefined && parsed[4] !== undefined) return native
106
- if (!valid && isNaN(Date.parse(`${date}Z`))) return native
124
+ if (parsed[1] == "-000000") {
125
+ return new Date(NaN)
126
+ }
127
+ if (zone === undefined && parsed[4] !== undefined) {
128
+ return native
129
+ }
130
+ if (!valid && isNaN(Date.parse(`${date}Z`))) {
131
+ return native
132
+ }
107
133
  const fraction = parsed[7]
108
134
  return date_of(
109
135
  [
110
- +(parsed[1] ?? NaN),
136
+ +/** @type {string} */(parsed[1])/**/,
111
137
  +(parsed[2] ?? 1) - 1,
112
138
  +(parsed[3] ?? 1),
113
139
  +(parsed[4] ?? 0),
@@ -120,11 +146,17 @@ export default function(date, format, zone) {
120
146
  zone
121
147
  )
122
148
  }
123
- if (zone === undefined) return native
149
+ if (zone === undefined) {
150
+ return native
151
+ }
124
152
  const text = date.replace(comment_regex, "")
125
- if (zone_regex.test(text)) return native
153
+ if (zone_regex.test(text)) {
154
+ return native
155
+ }
126
156
  const wall = new Date(`${text} GMT`)
127
- if (!valid && isNaN(wall.getTime())) return native
157
+ if (!valid && isNaN(wall.getTime())) {
158
+ return native
159
+ }
128
160
  return date_of(
129
161
  isNaN(wall.getTime())
130
162
  ? fields_of(native)
@@ -157,15 +189,23 @@ export default function(date, format, zone) {
157
189
  length = 6
158
190
  min = -271821
159
191
  }
160
- while (text.length < length && date.charCodeAt(index) > 47 && date.charCodeAt(index) < 58) text += date[index++]
161
- if (!text || sign && (text.length < 6 || sign == "-" && !+text)) return new Date(NaN)
192
+ while (text.length < length && date.charCodeAt(index) > 47 && date.charCodeAt(index) < 58) {
193
+ text += date[index++]
194
+ }
195
+ if (!text || sign && (text.length < 6 || sign == "-" && !+text)) {
196
+ return new Date(NaN)
197
+ }
162
198
  if (part[0] == 6) {
163
- while (date.charCodeAt(index) > 47 && date.charCodeAt(index) < 58) index++
199
+ while (date.charCodeAt(index) > 47 && date.charCodeAt(index) < 58) {
200
+ index++
201
+ }
164
202
  }
165
203
  const value = part[0] == 6
166
204
  ? +text.padEnd(3, "0")
167
205
  : +(sign + text)
168
- if (value > /** @type {number} */(part[3])/**/ || value < min) return new Date(NaN)
206
+ if (value > /** @type {number} */(part[3])/**/ || value < min) {
207
+ return new Date(NaN)
208
+ }
169
209
  fields[/** @type {number} */(part[0])/**/] = /** @type {number} */(part[0])/**/ == 1
170
210
  ? value - 1
171
211
  : value
@@ -173,6 +213,8 @@ export default function(date, format, zone) {
173
213
  if (index != date.length || /** @type {number} */(fields[2])/**/ > last_day(
174
214
  /** @type {number} */(fields[0])/**/,
175
215
  /** @type {number} */(fields[1])/**/
176
- )) return new Date(NaN)
216
+ )) {
217
+ return new Date(NaN)
218
+ }
177
219
  return date_of(fields, zone)
178
220
  }
package/src/zone.js CHANGED
@@ -7,9 +7,12 @@ const formatters = new Map()
7
7
  /**
8
8
  * @param {string} name
9
9
  * @param {string=} zone
10
+ * @returns {void}
10
11
  */
11
12
  function check_zone(name, zone) {
12
- if (zone === undefined || formatters.has(zone)) return
13
+ if (zone === undefined || formatters.has(zone)) {
14
+ return
15
+ }
13
16
  try {
14
17
  formatter_of(zone)
15
18
  } catch (error) {
@@ -25,9 +28,11 @@ function check_zone(name, zone) {
25
28
  * @returns {Date}
26
29
  */
27
30
  function date_of(fields, zone) {
28
- if (zone !== undefined) return new Date(
29
- instant_of(wall_of_fields(fields), zone)
30
- )
31
+ if (zone !== undefined) {
32
+ return new Date(
33
+ instant_of(wall_of_fields(fields), zone)
34
+ )
35
+ }
31
36
  const year = /** @type {number} */(fields[0])/**/
32
37
  if (year >= 0 && year < 100) {
33
38
  const date = new Date(0)
@@ -58,10 +63,14 @@ function date_of(fields, zone) {
58
63
  * @returns {number}
59
64
  */
60
65
  function end_at(wall, end, time, zone) {
61
- if (end < time) return wall - offset_in(time, zone) - 1
66
+ if (end < time) {
67
+ return wall - offset_in(time, zone) - 1
68
+ }
62
69
  const next = end + 1
63
70
  const offset = offset_in(next, zone)
64
- if (next + offset == wall || offset_in(end, zone) != offset) return end
71
+ if (next + offset == wall || offset_in(end, zone) != offset) {
72
+ return end
73
+ }
65
74
  const transition = transition_of(time, next, zone)
66
75
  return transition + offset_in(transition, zone) >= wall
67
76
  ? transition - 1
@@ -73,16 +82,18 @@ function end_at(wall, end, time, zone) {
73
82
  * @returns {number[]}
74
83
  */
75
84
  function fields_of(date, zone) {
76
- if (zone === undefined) return [
77
- date.getFullYear(),
78
- date.getMonth(),
79
- date.getDate(),
80
- date.getHours(),
81
- date.getMinutes(),
82
- date.getSeconds(),
83
- date.getMilliseconds(),
84
- date.getDay()
85
- ]
85
+ if (zone === undefined) {
86
+ return [
87
+ date.getFullYear(),
88
+ date.getMonth(),
89
+ date.getDate(),
90
+ date.getHours(),
91
+ date.getMinutes(),
92
+ date.getSeconds(),
93
+ date.getMilliseconds(),
94
+ date.getDay()
95
+ ]
96
+ }
86
97
  const time = date.getTime()
87
98
  return fields_of_wall(time + offset_of(time, zone))
88
99
  }
@@ -92,7 +103,9 @@ function fields_of(date, zone) {
92
103
  */
93
104
  function formatter_of(zone) {
94
105
  let formatter = formatters.get(zone)
95
- if (formatter) return formatter
106
+ if (formatter) {
107
+ return formatter
108
+ }
96
109
  formatter = new Intl.DateTimeFormat(
97
110
  "en-US",
98
111
  {
@@ -105,10 +118,14 @@ function formatter_of(zone) {
105
118
  if (known) {
106
119
  formatter = known
107
120
  } else {
108
- if (canonical.size >= 1000) canonical.clear()
121
+ if (canonical.size >= 1000) {
122
+ canonical.clear()
123
+ }
109
124
  canonical.set(name, formatter)
110
125
  }
111
- if (formatters.size >= 1000) formatters.clear()
126
+ if (formatters.size >= 1000) {
127
+ formatters.clear()
128
+ }
112
129
  formatters.set(zone, formatter)
113
130
  return formatter
114
131
  }
@@ -122,7 +139,9 @@ function instant_of(wall, zone, exact) {
122
139
  const before = offset_of(wall - 86400000, zone)
123
140
  const guess = wall - before
124
141
  const offset = offset_of(guess, zone)
125
- if (offset == before) return guess
142
+ if (offset == before) {
143
+ return guess
144
+ }
126
145
  const candidate = wall - offset
127
146
  return offset_of(candidate, zone) == offset
128
147
  ? candidate
@@ -155,10 +174,12 @@ function offset_of(time, zone) {
155
174
  : 8.64e15
156
175
  )
157
176
  )
158
- if (!match) return 0
177
+ if (!match) {
178
+ return 0
179
+ }
159
180
  return (match[1] == "-" ? -1 : 1) * (
160
- (+(match[2] ?? 0) * 60 + +(match[3] ?? 0)) * 60000
161
- + +(match[4] ?? 0) * 1000
181
+ (+/** @type {string} */(match[2])/**/ * 60 + +/** @type {string} */(match[3])/**/) * 60000
182
+ + +(match[4] ?? 0) * 1000
162
183
  )
163
184
  }
164
185
  /**
@@ -171,8 +192,11 @@ function transition_of(from, to, zone) {
171
192
  const offset = offset_in(to, zone)
172
193
  while (to - from > 1) {
173
194
  const middle = Math.floor((from + to) / 2)
174
- if (offset_in(middle, zone) == offset) to = middle
175
- else from = middle
195
+ if (offset_in(middle, zone) == offset) {
196
+ to = middle
197
+ } else {
198
+ from = middle
199
+ }
176
200
  }
177
201
  return to
178
202
  }
@@ -190,11 +214,17 @@ function unit_end(time, ms, zone) {
190
214
  for (;;) {
191
215
  const offset = offset_in(at, zone)
192
216
  const end = (bucket + 1) * ms - offset - 1
193
- if (!(end <= 8.64e15)) return NaN
194
- if (offset_in(end, zone) == offset) return end
217
+ if (!(end <= 8.64e15)) {
218
+ return NaN
219
+ }
220
+ if (offset_in(end, zone) == offset) {
221
+ return end
222
+ }
195
223
  const transition = transition_of(at, end, zone)
196
224
  const wall = transition + offset_in(transition, zone)
197
- if (Math.floor(wall / ms) != bucket || wall <= transition - 1 + offset) return transition - 1
225
+ if (Math.floor(wall / ms) != bucket || wall <= transition - 1 + offset) {
226
+ return transition - 1
227
+ }
198
228
  at = transition
199
229
  }
200
230
  }
@@ -212,12 +242,18 @@ function unit_start(time, ms, zone) {
212
242
  for (;;) {
213
243
  const offset = offset_in(at, zone)
214
244
  const start = bucket * ms - offset
215
- if (!(start >= -8.64e15)) return NaN
216
- if (offset_in(start, zone) == offset) return start
245
+ if (!(start >= -8.64e15)) {
246
+ return NaN
247
+ }
248
+ if (offset_in(start, zone) == offset) {
249
+ return start
250
+ }
217
251
  const transition = transition_of(start, at, zone)
218
252
  const before = transition - 1
219
253
  const wall = before + offset_in(before, zone)
220
- if (Math.floor(wall / ms) != bucket || wall >= transition + offset) return transition
254
+ if (Math.floor(wall / ms) != bucket || wall >= transition + offset) {
255
+ return transition
256
+ }
221
257
  at = before
222
258
  }
223
259
  }
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../src/add.js"],"names":[],"mappings":"AAqEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAzBjB,IAyBiB,EAAE,GAAG,EAxBtB,MAwBsB,EAAE,IAAI,AAVpC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUH,GAT1B,IAAI,CAuDhB"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../src/add.js"],"names":[],"mappings":"AAgFA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAzBjB,IAyBiB,EAAE,GAAG,EAxBtB,MAwBsB,EAAE,IAAI,AAVpC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUH,GAT1B,IAAI,CA6DhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../src/calendar.js"],"names":[],"mappings":"AACA;;;;;GAKG;AACH,iBAAS,OAAO,CAAC,IAAI,EALV,MAKU,EAAE,KAAK,EAJjB,MAIiB,EAAE,GAAG,EAHtB,MAGsB,GAFpB,MAAM,CAmBlB;AACD;;;GAGG;AACH,iBAAS,cAAc,CAAC,IAAI,EAHjB,MAGiB,GAFf,MAAM,EAAE,CA6BpB;AACD;;;;GAIG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAJX,MAIW,EAAE,KAAK,EAHlB,MAGkB,GAFhB,MAAM,CAMlB;AACD;;;GAGG;AACH,iBAAS,cAAc,CAAC,MAAM,EAHnB,MAAM,EAGa,GAFjB,MAAM,CAYlB;AACD,OAAO,EACN,OAAO,EACP,cAAc,EACd,QAAQ,EACR,cAAc,EACd,CAAA"}
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../src/calendar.js"],"names":[],"mappings":"AACA;;;;;GAKG;AACH,iBAAS,OAAO,CAAC,IAAI,EALV,MAKU,EAAE,KAAK,EAJjB,MAIiB,EAAE,GAAG,EAHtB,MAGsB,GAFpB,MAAM,CAqBlB;AACD;;;GAGG;AACH,iBAAS,cAAc,CAAC,IAAI,EAHjB,MAGiB,GAFf,MAAM,EAAE,CA6BpB;AACD;;;;GAIG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAJX,MAIW,EAAE,KAAK,EAHlB,MAGkB,GAFhB,MAAM,CAMlB;AACD;;;GAGG;AACH,iBAAS,cAAc,CAAC,MAAM,EAHnB,MAAM,EAGa,GAFjB,MAAM,CAYlB;AACD,OAAO,EACN,OAAO,EACP,cAAc,EACd,QAAQ,EACR,cAAc,EACd,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"date_to_string.d.ts","sourceRoot":"","sources":["../src/date_to_string.js"],"names":[],"mappings":"AAsDA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,WACb,IAAI,EAxBM,IAwBN,EACJ,MAAM,AAxBJ,CAaA,EAbQ,MAAM,YAwBkB,EAClC,IAAI,AAZF,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAYrC,GAXQ,MAAM,CAgClB"}
1
+ {"version":3,"file":"date_to_string.d.ts","sourceRoot":"","sources":["../src/date_to_string.js"],"names":[],"mappings":"AA8DA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,WACb,IAAI,EAxBM,IAwBN,EACJ,MAAM,AAxBJ,CAaA,EAbQ,MAAM,YAwBkB,EAClC,IAAI,AAZF,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAYrC,GAXQ,MAAM,CAkClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.js"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAhBjB,IAgBiB,EAAE,EAAE,EAfrB,IAeqB,EAAE,IAAI,EAd3B,OAAO,cAAc,EAAE,IAcI,EAAE,IAAI,AAVzC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUE,GAT/B,MAAM,CAiFlB"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.js"],"names":[],"mappings":"AAoDA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAhBjB,IAgBiB,EAAE,EAAE,EAfrB,IAeqB,EAAE,IAAI,EAd3B,OAAO,cAAc,EAAE,IAcI,EAAE,IAAI,AAVzC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUE,GAT/B,MAAM,CAkGlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"end_of.d.ts","sourceRoot":"","sources":["../src/end_of.js"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAfjB,IAeiB,EAAE,IAAI,EAdvB,OAAO,CAAC,OAAO,cAAc,EAAE,IAAI,EAAE,KAAK,CAcnB,EAAE,IAAI,AAVrC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUF,GAT3B,IAAI,CAsFhB"}
1
+ {"version":3,"file":"end_of.d.ts","sourceRoot":"","sources":["../src/end_of.js"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAfjB,IAeiB,EAAE,IAAI,EAdvB,OAAO,CAAC,OAAO,cAAc,EAAE,IAAI,EAAE,KAAK,CAcnB,EAAE,IAAI,AAVrC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUF,GAT3B,IAAI,CAmGhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"start_of.d.ts","sourceRoot":"","sources":["../src/start_of.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAfjB,IAeiB,EAAE,IAAI,EAdvB,OAAO,CAAC,OAAO,cAAc,EAAE,IAAI,EAAE,KAAK,CAcnB,EAAE,IAAI,AAVrC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUF,GAT3B,IAAI,CAqFhB"}
1
+ {"version":3,"file":"start_of.d.ts","sourceRoot":"","sources":["../src/start_of.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAfjB,IAeiB,EAAE,IAAI,EAdvB,OAAO,CAAC,OAAO,cAAc,EAAE,IAAI,EAAE,KAAK,CAcnB,EAAE,IAAI,AAVrC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YAUF,GAT3B,IAAI,CAqGhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"string_to_date.d.ts","sourceRoot":"","sources":["../src/string_to_date.js"],"names":[],"mappings":"AAuDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAvBjB,MAuBiB,EAAE,MAAM,AAtBjC,CAaA,EAbQ,MAAM,YAsBmB,EAAE,IAAI,AATvC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YASA,GAR7B,IAAI,CAgGhB"}
1
+ {"version":3,"file":"string_to_date.d.ts","sourceRoot":"","sources":["../src/string_to_date.js"],"names":[],"mappings":"AAoEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,OAAO,WAAU,IAAI,EAvBjB,MAuBiB,EAAE,MAAM,AAtBjC,CAaA,EAbQ,MAAM,YAsBmB,EAAE,IAAI,AATvC,CACA,EADQ,OAAO,cAAc,EAAE,QAAQ,YASA,GAR7B,IAAI,CA6HhB"}
package/types/zone.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @param {string} name
3
3
  * @param {string=} zone
4
+ * @returns {void}
4
5
  */
5
6
  declare function check_zone(name: string, zone?: string | undefined): void;
6
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"zone.d.ts","sourceRoot":"","sources":["../src/zone.js"],"names":[],"mappings":"AAMA;;;GAGG;AACH,iBAAS,UAAU,CAAC,IAAI,EAHb,MAGa,EAAE,IAAI,AAF3B,CACF,EADU,MAAM,YAEa,QAU7B;AACD;;;;GAIG;AACH,iBAAS,OAAO,CAAC,MAAM,EAJZ,MAAM,EAIM,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,IAAI,CA2BhB;AACD;;;;;;GAMG;AACH,iBAAS,MAAM,CAAC,IAAI,EANT,MAMS,EAAE,GAAG,EALd,MAKc,EAAE,IAAI,EAJpB,MAIoB,EAAE,IAAI,AAHlC,CACA,EADQ,MAAM,YAGoB,GAFxB,MAAM,CAWlB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,IAIY,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,MAAM,EAAE,CAepB;AA2BD;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,IAAI,EAJnB,MAImB,EAAE,KAAK,AAHlC,CACA,EADQ,OAAO,YAGmB,GAFxB,MAAM,CAalB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,MAIY,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,MAAM,CAMlB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,MAIY,EAAE,IAAI,EAHlB,MAGkB,GAFhB,MAAM,CAiBlB;AACD;;;;;GAKG;AACH,iBAAS,aAAa,CAAC,IAAI,EALhB,MAKgB,EAAE,EAAE,EAJpB,MAIoB,EAAE,IAAI,AAHlC,CACA,EADQ,MAAM,YAGoB,GAFxB,MAAM,CAUlB;AACD;;;;;GAKG;AACH,iBAAS,QAAQ,CAAC,IAAI,EALX,MAKW,EAAE,EAAE,EAJf,MAIe,EAAE,IAAI,AAH7B,CACA,EADQ,MAAM,YAGe,GAFnB,MAAM,CAiBlB;AACD;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,EAAE,EAJjB,MAIiB,EAAE,IAAI,AAH/B,CACA,EADQ,MAAM,YAGiB,GAFrB,MAAM,CAkBlB;AACD,OAAO,EACN,UAAU,EACV,OAAO,EACP,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,UAAU,EACV,CAAA"}
1
+ {"version":3,"file":"zone.d.ts","sourceRoot":"","sources":["../src/zone.js"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,iBAAS,UAAU,CAAC,IAAI,EAJb,MAIa,EAAE,IAAI,AAH3B,CACA,EADQ,MAAM,YAGa,GAFjB,IAAI,CAchB;AACD;;;;GAIG;AACH,iBAAS,OAAO,CAAC,MAAM,EAJZ,MAAM,EAIM,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,IAAI,CA6BhB;AACD;;;;;;GAMG;AACH,iBAAS,MAAM,CAAC,IAAI,EANT,MAMS,EAAE,GAAG,EALd,MAKc,EAAE,IAAI,EAJpB,MAIoB,EAAE,IAAI,AAHlC,CACA,EADQ,MAAM,YAGoB,GAFxB,MAAM,CAelB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,IAIY,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,MAAM,EAAE,CAiBpB;AAiCD;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,IAAI,EAJnB,MAImB,EAAE,KAAK,AAHlC,CACA,EADQ,OAAO,YAGmB,GAFxB,MAAM,CAelB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,MAIY,EAAE,IAAI,AAH1B,CACA,EADQ,MAAM,YAGY,GAFhB,MAAM,CAMlB;AACD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,IAAI,EAJZ,MAIY,EAAE,IAAI,EAHlB,MAGkB,GAFhB,MAAM,CAmBlB;AACD;;;;;GAKG;AACH,iBAAS,aAAa,CAAC,IAAI,EALhB,MAKgB,EAAE,EAAE,EAJpB,MAIoB,EAAE,IAAI,AAHlC,CACA,EADQ,MAAM,YAGoB,GAFxB,MAAM,CAalB;AACD;;;;;GAKG;AACH,iBAAS,QAAQ,CAAC,IAAI,EALX,MAKW,EAAE,EAAE,EAJf,MAIe,EAAE,IAAI,AAH7B,CACA,EADQ,MAAM,YAGe,GAFnB,MAAM,CAuBlB;AACD;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,EAAE,EAJjB,MAIiB,EAAE,IAAI,AAH/B,CACA,EADQ,MAAM,YAGiB,GAFrB,MAAM,CAwBlB;AACD,OAAO,EACN,UAAU,EACV,OAAO,EACP,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,UAAU,EACV,CAAA"}