# time_zone

> The IANA time zone name, such as Europe/Berlin, from Intl; a UTC offset when Intl is missing.

Source: https://whiskerjs.com/signals/time-zone/ (last updated 2026-10-26)

**time_zone at a glance (from the library code, signalsVersion 9)**

| Field | Value |
| --- | --- |
| Component name | `time_zone` |
| In the visitorId | yes |
| structuredId group | [locale](https://whiskerjs.com/docs/identifiers/#structuredid) |
| Hashing | plain value; a digest only when longer than 128 characters or not printable ASCII |
| Excluded under | Firefox resistFingerprinting (firefox_rfp); Tor Browser and Mullvad Browser (rfp_hardened) |
| Inner timeout | 1000 ms |
| Added in | [signalsVersion 1](https://whiskerjs.com/whats-new/) |

> **In plain words:**
>
> Your computer or phone knows which time zone it is set to, for example Europe/Berlin or America/New_York, and browsers tell pages so they can show local times. WhiskerJS reads the name as it is. It is a simple, rarely changing setting, and a useful check against where your server thinks the visitor is.

## What it reads

The `timeZone` field of `new Intl.DateTimeFormat().resolvedOptions()`. If Intl is missing or gives nothing, WhiskerJS falls back to the offsets of 1 January and 1 July (of the year 2000) from `Date.prototype.getTimezoneOffset()`, takes the larger one (in minutes, as that method returns them) and reports it as `UTC+n` or `UTC-n`.

## How the technique works

The IANA name is the operating system’s time zone setting as the JavaScript engine sees it. It is more precise than an offset: two zones can share an offset today and differ in their daylight saving rules. The fallback uses two dates half a year apart so that daylight saving does not change the reported value from season to season.

The same Intl time zone also feeds the browser class: Firefox is only classed `firefox_rfp` (or `rfp_hardened`) when, among other traits, the time zone is `UTC`, `Etc/UTC` or `Atlantic/Reykjavik`. The [`timezone_inconsistent`](https://whiskerjs.com/docs/integrity/#timezone_inconsistent) integrity flag compares the offset of this Intl zone with `Date.prototype.getTimezoneOffset()` in January and July, which catches a zone spoofed in one API but not the other.

## Why it helps

Time zones split visitors by region, and the value rarely changes for a given device. It is in the `locale` group of the [structuredId](https://whiskerjs.com/glossary/#structured-id), so a change of only that part often means a travel or a settings change rather than a new device.

## Stability

It changes when the user travels and the device updates its time zone automatically, when the user changes it by hand, and in rare cases when time zone rules or names are updated in the operating system’s data.

## Browser support and what blocks it

- `ok` in all current browsers.
- [Firefox resistFingerprinting](https://whiskerjs.com/browsers/firefox-rfp-and-tor/): `excluded` / `firefox_rfp`; [Tor Browser and Mullvad Browser](https://whiskerjs.com/browsers/firefox-rfp-and-tor/): `excluded` / `rfp_hardened`.
- Not excluded in [Brave](https://whiskerjs.com/browsers/brave/).

The [`iframe_mismatch`](https://whiskerjs.com/docs/integrity/#iframe_mismatch) check compares the Intl time zone with a clean iframe, and [`native_tampering`](https://whiskerjs.com/docs/integrity/#native_tampering) checks `Intl.DateTimeFormat.prototype.resolvedOptions` and `Date.prototype.getTimezoneOffset` for patches, which is how time zone spoofing scripts often show themselves.

On your server, compare it with the region of the request’s IP address. A large difference is worth a look, but VPNs, travel and corporate networks explain many of them; see [Recommended server checks](https://whiskerjs.com/docs/integration/#recommended-server-checks).

## Privacy

A coarse location hint at time zone level, chosen by the operating system. No permission, no geolocation, no prompt, no request.

## How WhiskerJS handles noise and failures

| Status | ruleId | When |
| --- | --- | --- |
| `ok` | none | an IANA name or a `UTC+n` fallback |
| `unavailable` | `no_api` | neither Intl nor Date gave a value |
| `blocked` | `security_error`, `threw` | reading threw outside the guards |
| `excluded` | `firefox_rfp`, `rfp_hardened`, `caller_excluded` | exclusion table or your list |
| `timed_out` | `timeout`, `aborted` | 1000 ms inner timeout, budget, abort |

## Example value

```json
"time_zone": { "status": "ok", "value": "Europe/Berlin", "hashed": false }
```

## Questions and answers

### Does time_zone reveal my location?

Only at the level of a time zone, which usually covers a region or country. It is set by the operating system, not measured from GPS or the network.

### Why is time_zone excluded under Firefox resistFingerprinting?

That mode (also in Tor Browser and Mullvad Browser) always reports UTC (newer releases Atlantic/Reykjavik), so the value says nothing about the device. The exclusion table reports excluded with ruleId firefox_rfp, or rfp_hardened for Tor and Mullvad.

### Why does my automated test show UTC?

Many servers, containers and automation tools run in UTC. The headless test browsers used for these pages all reported UTC.

## Related pages

- [intl_locale](https://whiskerjs.com/signals/intl-locale/): Locale, calendar and hour cycle.
- [languages](https://whiskerjs.com/signals/languages/): The browser's language list.
- [resistFingerprinting](https://whiskerjs.com/glossary/#resistfingerprinting): Firefox's normalising mode.
- [Recommended server checks](https://whiskerjs.com/docs/integration/#recommended-server-checks): Comparing the time zone with the IP address region.
- [iframe_mismatch flag](https://whiskerjs.com/docs/integrity/#iframe_mismatch): Compares the Intl time zone with a clean frame.
