# Australian browser-clock check

A small Playwright fixture separates a browser's time zone from the Node.js runner and network path. It starts a server on `127.0.0.1`, opens 12 fresh Chromium contexts, reads a clock rendered by the page, prints JSON, and closes the browser and server. It needs no credentials or proxy. After dependency installation, the fixture makes only requests to its own loopback origin and blocks any other page request.

Use Node.js 24. These shell commands work on macOS/Linux; on Linux, install Playwright's documented browser system dependencies if the browser cannot start.

```sh
mkdir australia-clock-demo
cd australia-clock-demo
curl --fail --silent --show-error --output australia-clock-check.mjs https://ipvolt.com/downloads/australia-clock-check.mjs
npm install --no-audit --no-fund --save-exact playwright@1.63.0
npx playwright install chromium
TZ=UTC node australia-clock-check.mjs > results-utc.json
```

An exit status of `0` and `summary.allPassed: true` mean all 12 clock cases and the fixture's request/error checks passed. An exit status of `1` means an assertion failed; the JSON keeps the failing row IDs and per-row assertions. A startup or dependency error goes to standard error and is not a passing run.

The recorded reference run used Node.js 24.20.0, Playwright 1.63.0 and Chromium 153.0.8010.12 on macOS arm64. [Reference JSON](https://ipvolt.com/downloads/australia-clock-results.json) retains the assertions and environment; [reference CSV](https://ipvolt.com/downloads/australia-clock-results.csv) provides selected row fields. Your installed browser's recorded version may differ after an upgrade.

Every row sets the browser's `timezoneId`, then fixes an explicit UTC instant with `page.clock.setFixedTime` before loading the page. Offsets are minutes **east** of UTC, the opposite sign to JavaScript's `getTimezoneOffset()`. The January/July cases use `2026-01-15T00:00:00Z` and `2026-07-15T00:00:00Z`:

| Browser zone | January wall clock / offset | July wall clock / offset |
| --- | --- | --- |
| Australia/Sydney | 11:00 / +660 | 10:00 / +600 |
| Australia/Brisbane | 10:00 / +600 | 10:00 / +600 |
| Australia/Broken_Hill | 10:30 / +630 | 09:30 / +570 |
| Australia/Lord_Howe | 11:00 / +660 | 10:30 / +630 |

Four further snapshots straddle the modelled 4 October 2026 changes. Lord Howe moves from `01:59:59` to `02:30:00` while UTC advances one second (`2026-10-03T15:29:59Z` to `15:30:00Z`). Sydney moves from `01:59:59` to `03:00:00` across `15:59:59Z` to `16:00:00Z`. These are fixed-time browser observations, not monitoring of a live transition.

Run the same file with another runner time zone:

```sh
TZ=Australia/Perth node australia-clock-check.mjs > results-perth.json
```

The 12 `browser` readings should match the UTC-runner file. The `runner` fields should now identify `Australia/Perth` with offset `480`, while the UTC runner reports offset `0`. Both should pass. Browser emulation has not reconfigured Node's time zone.

The following deliberately wrong modes should each exit `1`. Run them separately when a shell or CI job stops on a failing command:

```sh
TZ=UTC node australia-clock-check.mjs one-nsw-clock > wrong-nsw.json
TZ=UTC node australia-clock-check.mjs one-hour-dst > wrong-dst.json
TZ=UTC node australia-clock-check.mjs omit-browser-timezone > wrong-browser-zone.json
```

`one-nsw-clock` substitutes Sydney-like expectations for Broken Hill and Lord Howe. `one-hour-dst` expects Lord Howe's summer offset to be +690 minutes instead of +660. `omit-browser-timezone` retains the Australian expectations while leaving the browser at the UTC runner's default. The first two modes deliberately corrupt expectations; the third removes a browser control. Their failures demonstrate the test's ability to detect those specific mistakes.

To reuse the approach in your application, keep the explicit UTC input and browser setting, then replace the fixture's visible-clock assertion with your page's expected schedule or date. The script itself accepts no external target URL. A real application's server-side zone, stored preferences, business rules and proxy egress need their own controls and assertions.

This fixture checks Chromium's date rendering at the declared instants. It does not test timer progression, repeated wall times when clocks move backward, every Australian territory, other browser engines, Australian IP geography, proxy inventory, network identity, latency or carrier access. `setFixedTime` fixes `Date.now()` and `new Date()` while timers continue normally. Browser and server time-zone data can differ; keep the JSON environment record and recheck expectations when upgrading or changing dates.

Sources: [Playwright locale and time-zone emulation](https://playwright.dev/docs/emulation#locale--timezone), [Playwright fixed time API](https://playwright.dev/docs/api/class-clock#clock-set-fixed-time), [NSW time definitions and exceptions](https://dcj.nsw.gov.au/about-us/daylight-saving/definitions-of-time-and-how-time-is-regulated.html), [NSW daylight-saving dates](https://www.nsw.gov.au/about-nsw/daylight-saving), [IANA Australasian time-zone rules](https://data.iana.org/time-zones/tzdb/australasia), [Node.js TZ configuration](https://nodejs.org/docs/latest-v24.x/api/cli.html#tz).
