Compare Logs Across UTC, PST, and JST in One View (2026)
Learn how to compare logs across UTC, PST, and JST in one view: normalize to Unix time, then convert cleanly with IANA zone names and ISO 8601.
Compare Logs Across UTC, PST, and JST in One View
You have three log files: an API server writing UTC, a developer's laptop in Pacific time, and a regional node in Tokyo. A user reports a failed request, and you need to line up what each system did in the same second. Comparing logs across UTC, PST, and JST by eye is where bugs hide — an hour here, a calendar day there. The reliable fix is to stop reading the printed time and start reading the Unix timestamp underneath it.
TL;DR
- Normalize every log line to Unix time first; epoch seconds are zone-agnostic.
- Sort by epoch, then render that one number in UTC, PST, and JST.
- JST is UTC+9 with no DST; Pacific flips between PST (-8) and PDT (-7).
- Use IANA names like
America/Los_Angeles, never a hard-coded offset. - Log in UTC with an ISO 8601 string ending in
Zto avoid the whole problem.
Why comparing logs across time zones goes wrong
Most cross-zone log bugs are not exotic. They come from treating a printed timestamp as if it were the actual moment, when it is really a moment plus a hidden offset you forgot to account for.
The "off by 3 hours" bug nobody catches in review
A log line like 14:05:22 tells you nothing on its own. Fourteen-oh-five where? If the API logs UTC and your laptop logs Pacific, two lines that look three hours apart may be the exact same instant. Reviewers skim right past this because both timestamps look plausible. The only way to be sure is to convert both to a common reference and compare the numbers, not the wall-clock strings.
PST is not "Pacific Time" (and why that matters)
People say "PST" to mean "the time in California," but PST specifically means UTC-8, the standard (winter) offset. From the second Sunday in March to the first Sunday in November, the Pacific zone is actually on PDT, which is UTC-7. If you hard-code -8 for a June log, every line is off by an hour. This is why you reach for the zone region (America/Los_Angeles) and let the time library decide whether PST or PDT applies on that date.
When your servers disagree about "now"
A request can be logged at 2026-06-08T20:05:00Z on the API, 13:05 on a Pacific worker, and the next calendar day in Tokyo. Because JST is 16 hours ahead of PDT, an evening event in California is often already "tomorrow" in Japan. Sorting log lines alphabetically by their printed timestamp scrambles the real order. Sorting by epoch never does.
How to compare logs from UTC, PST, and JST in one view
The workflow is always the same three moves: normalize, convert, align. Do them in that order and the time zones stop fighting you.
Step 1: normalize everything to Unix time
Unix time is the number of seconds since 1970-01-01T00:00:00Z. It carries no offset, so it is the same integer everywhere on Earth at a given instant. Parse each log line, extract its timestamp with its offset, and reduce it to one epoch number. If a line shows 13:05:00-07:00, that is the same instant as 20:05:00Z — per RFC 3339, the offset is "local time minus UTC," so you subtract it to get UTC.
Paste any of these into a converter to confirm they collapse to the same number:
2026-06-08T20:05:00Z -> 1780949100
2026-06-08T13:05:00-07:00 -> 1780949100
2026-06-09T05:05:00+09:00 -> 1780949100
All three are the same instant. The Unix Timestamp Converter turns each of these strings into the epoch seconds and back, so you can verify alignment without trusting your mental arithmetic.
Step 2: convert the epoch to each zone
Once every event is an epoch number, rendering it in three zones is a display concern. In JavaScript a Date always holds a UTC instant internally; Intl.DateTimeFormat simply paints that instant in whatever zone you name, as the MDN docs describe.
const epoch = 1780949100; // seconds
const d = new Date(epoch * 1000);
const show = (tz) =>
new Intl.DateTimeFormat("en-US", {
timeZone: tz,
dateStyle: "short",
timeStyle: "medium",
timeZoneName: "short",
}).format(d);
show("UTC"); // UTC view
show("America/Los_Angeles"); // PST or PDT, auto
show("Asia/Tokyo"); // JST
Note you never write -8 or +9. You name the region and the runtime applies the correct rule for that date.
Step 3: line them up on one axis
Now build a single table keyed by epoch. Each row is one event; each column is the same instant in a different zone. Because the rows share an epoch key, you can interleave lines from three files and sort the merged stream by that key. The result reads as one chronological story.
| Zone | IANA name | Standard offset | Observes DST |
|---|---|---|---|
| UTC | Etc/UTC |
+00:00 | No |
| Pacific | America/Los_Angeles |
-08:00 (PST) | Yes → -07:00 (PDT) |
| Japan | Asia/Tokyo |
+09:00 (JST) | No |
JST never moves, so it is a stable anchor. Pacific is the column most likely to surprise you twice a year.
How to convert a Unix timestamp to PST and JST
You will not always be in a browser. Here are the same conversions in two other common environments, plus the offsets you should expect.
Using JavaScript Intl.DateTimeFormat
The browser snippet above is the canonical approach. The key facts: a Date is a UTC instant, multiply epoch seconds by 1000 to get milliseconds, and pass an IANA timeZone to Intl.DateTimeFormat. Add timeZoneName: "short" and the output literally prints PST, PDT, or JST, so a reader can confirm which offset was applied.
Using Python zoneinfo
Python's standard library ships IANA zone support through the zoneinfo module, so you do not need a third-party package.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
epoch = 1780949100
utc = datetime.fromtimestamp(epoch, tz=timezone.utc)
print(utc)
print(utc.astimezone(ZoneInfo("America/Los_Angeles")))
print(utc.astimezone(ZoneInfo("Asia/Tokyo")))
astimezone does the DST math for you based on the instant and the named zone.
Using the command line (date)
On Linux and macOS, date reads the TZ environment variable:
TZ=UTC date -d @1780949100
TZ=America/Los_Angeles date -d @1780949100
TZ=Asia/Tokyo date -d @1780949100
On macOS use date -r 1780949100 instead of -d @. The @ syntax says "this is an epoch value," which sidesteps any parsing ambiguity.
Why you should log in UTC with an ISO 8601 timestamp
The cleanest cross-zone comparison is the one you never have to do, because every system already logs the same way.
What RFC 3339 actually requires
RFC 3339 is the internet profile of ISO 8601. It uses T to separate date and time and Z to mark UTC, so 2026-06-08T20:05:00Z is unambiguous worldwide. RFC 3339 even distinguishes -00:00 (offset unknown, UTC preferred) from Z (definitely UTC) — a subtlety worth knowing when you parse third-party logs. Emit this format from every service and your "comparison" becomes a plain string sort.
IANA zone names vs fixed offsets
A fixed offset like -08:00 is a fact about one instant; an IANA name like America/Los_Angeles is a rule that knows the entire history of that region's offsets and DST transitions. The IANA Time Zone Database is updated whenever a government changes its rules, which is exactly why you store the region name and resolve the offset at display time rather than freezing a number.
Handling DST without losing your mind
DST creates two genuinely hard hours per year: a "spring forward" gap where a local time never happens, and a "fall back" hour that happens twice. Local timestamps can collide or vanish during those windows. UTC has neither problem because it never shifts. Log UTC, convert late, and the only zone that ever does DST math is the display layer.
Reading messy logs that already mix time zones
Sometimes you inherit logs you cannot fix at the source. Here is how to normalize them after the fact.
Spotting the offset in a raw line
Scan each timestamp for its trailing zone marker: Z, +09:00, -0700, or a name like JST. If a line has no offset at all, you have to know the producing system's zone out of band — that ambiguity is the single biggest reason to standardize on UTC. Treat an offset-less timestamp as a warning, not a value.
Extracting timestamps with regex
When timestamps are buried in free-form lines, pull them out with a pattern before converting. A Regex Tester lets you build and verify the pattern against real log samples first:
- ISO-ish:
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\S* - Bracketed:
\[(.*?)\] - Epoch in a field:
\b1[0-9]{9}\b(10-digit seconds)
Capture the match, feed it to your converter, and key the line by the resulting epoch.
Diffing two log files after normalizing
Once both files are rewritten to UTC epochs, a line-by-line comparison finally means something. A Diff Checker will highlight where two normalized logs diverge, instead of showing every line as "different" just because one printed PST and the other JST. Normalize first, diff second.
References
- RFC 3339 — Date and Time on the Internet: Timestamps — used for the offset-equals-"local minus UTC" rule and the
-00:00vsZdistinction. - IANA Time Zone Database — source for Area/Location naming and why region names beat fixed offsets.
- MDN: Intl.DateTimeFormat —
timeZoneandtimeZoneNameoptions used in the JavaScript example. - Python docs: zoneinfo — IANA time zone support — standard-library
ZoneInfoused in the Python conversion snippet.
Related on iKit
- Convert a Unix timestamp to a date without timezone bugs — the deep dive on the offset and DST traps this article keeps you out of.
- Decode the 10-digit Unix timestamps hiding in your logs — how to recognize and read epoch values inside raw log lines before you compare them.
- The epoch time cheat sheet: seconds, millis, micros, nanos — make sure you are multiplying by the right factor when an epoch is in milliseconds.
- Why your JavaScript timestamp is 1000× bigger than your backend's — the seconds-vs-milliseconds mismatch that breaks cross-system comparisons.
- Postgres extract(epoch) vs MySQL UNIX_TIMESTAMP() — what each database actually returns when you pull epochs out for comparison.
Related posts
How to Test a Regex Pattern Online in 30 Seconds (2026)
Learn how to test a regex pattern online without writing code: paste, highlight, and debug matches, plus why the same regex passes in Python but fails in JS.
Convert a Date to Unix Timestamp: Bash, Python, JS, SQL (2026)
Convert any date to a Unix timestamp in Bash, Python, JavaScript, and SQL with copy-paste one-liners — plus the timezone trap each language hides.
Convert PNG to WebP and Cut Image Size by 30% (2026)
Convert PNG to WebP to cut image size by roughly 30% with no visible quality loss. A 2026 guide to lossless vs lossy, the Canvas API, and browser support.