(parts: WallClock, timezone?: string)
| 76 | * of drifting backwards into the gap (which used to yield a past date). |
| 77 | */ |
| 78 | export function localTimeToTimestamp(parts: WallClock, timezone?: string): number { |
| 79 | const guess = Date.UTC( |
| 80 | parts.year, parts.month - 1, parts.day, |
| 81 | parts.hour, parts.minute, parts.second, parts.millisecond |
| 82 | ); |
| 83 | |
| 84 | const firstOffset = getOffsetMinutes(new Date(guess), timezone); |
| 85 | const candidate1 = guess - firstOffset * 60000; |
| 86 | |
| 87 | const secondOffset = getOffsetMinutes(new Date(candidate1), timezone); |
| 88 | if (secondOffset === firstOffset) { |
| 89 | return candidate1; |
| 90 | } |
| 91 | |
| 92 | const candidate2 = guess - secondOffset * 60000; |
| 93 | if (readsBackTo(candidate1, parts, timezone)) return candidate1; |
| 94 | if (readsBackTo(candidate2, parts, timezone)) return candidate2; |
| 95 | |
| 96 | // Non-existent local time (spring-forward gap): resolve forward. |
| 97 | return Math.max(candidate1, candidate2); |
| 98 | } |
| 99 | |
| 100 | // Constructing an Intl.DateTimeFormat is expensive (~90us each on V8) while |
| 101 | // reusing one is ~16x cheaper. A formatter only depends on the timezone, so we |
no test coverage detected