@dboio/cli 0.7.2 → 0.8.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.
@@ -20,20 +20,42 @@ export function parseServerDate(dateStr, serverTz) {
20
20
  if (!serverTz || serverTz === 'UTC') return asUtc;
21
21
 
22
22
  // Find offset: format this UTC instant in the server timezone,
23
- // then compute the difference to determine the actual UTC time
24
- const parts = new Intl.DateTimeFormat('en-US', {
23
+ // then compute the difference to determine the actual UTC time.
24
+ // Use hourCycle:'h23' (range 0-23) to avoid the hour12:false quirk where
25
+ // midnight is returned as "24" instead of "00" on some V8 versions.
26
+ const fmt = new Intl.DateTimeFormat('en-US', {
25
27
  timeZone: serverTz,
26
28
  year: 'numeric', month: '2-digit', day: '2-digit',
27
29
  hour: '2-digit', minute: '2-digit', second: '2-digit',
28
- hour12: false,
29
- }).formatToParts(asUtc);
30
+ hourCycle: 'h23',
31
+ });
30
32
 
31
- const p = {};
32
- for (const { type, value } of parts) p[type] = value;
33
- const tzLocal = new Date(`${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}:${p.second}Z`);
34
- const offset = tzLocal - asUtc;
33
+ // Helper: compute the UTC offset (ms) for a given UTC instant in serverTz.
34
+ // Returns the offset such that: localTime (as UTC) = utcInstant + offset.
35
+ const getOffset = (utcInstant) => {
36
+ const parts = fmt.formatToParts(utcInstant);
37
+ const p = {};
38
+ for (const { type, value } of parts) p[type] = value;
39
+ const tzLocal = new Date(`${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}:${p.second}Z`);
40
+ if (isNaN(tzLocal.getTime())) return null;
41
+ return tzLocal - utcInstant;
42
+ };
35
43
 
36
- return new Date(asUtc.getTime() - offset);
44
+ // Step 1: estimate the UTC equivalent by computing the offset at asUtc.
45
+ // asUtc is the server's local time naively parsed as UTC, so it may sit in
46
+ // a different DST regime than the true UTC. This gives a rough approximation.
47
+ const offset1 = getOffset(asUtc);
48
+ if (offset1 === null) return asUtc; // fallback: treat as UTC
49
+
50
+ const approx = new Date(asUtc.getTime() - offset1);
51
+
52
+ // Step 2: recompute the offset at the approximated true UTC.
53
+ // This corrects for DST boundary crossings where step 1 used the wrong
54
+ // summer/winter offset — one iteration is sufficient since DST shifts by 1h.
55
+ const offset2 = getOffset(approx);
56
+ if (offset2 === null) return approx;
57
+
58
+ return new Date(asUtc.getTime() - offset2);
37
59
  }
38
60
 
39
61
  /**