A Unix timestamp is not "in" a time zone. It is a running count of seconds since 1970-01-01 00:00:00 UTC. The number itself is timezone-agnostic. The confusion starts the moment you try to display it as a human-readable date. Here is how to convert that integer to GMT without double-shifting, misformatting, or confusing it with London time in July.
How a Unix Timestamp Works
A Unix timestamp is an integer. It counts seconds, not dates. The starting point is the Unix epoch: 1970-01-01 00:00:00 UTC. No daylight saving, no leap seconds, no local time adjustments. Just a running tally.
The same timestamp represents one instant everywhere. That instant is 12:00 UTC in Greenwich, 07:00 in New York, and 23:00 in Tokyo. Same moment, different wall clocks.
Why the Timestamp Is Always UTC
Unix timestamps are always UTC. Not "usually." Not "by convention." Always. The timestamp carries no offset, no time zone database, and no memory of where it was created.
Servers are often set to UTC for exactly this reason. If the server clock is wrong, the timestamps are wrong. If an application stores a timestamp as a local time string, the data is already compromised. The Unix timestamp sidesteps this entirely: it is timezone-agnostic until you format it.
The practical rule: store timestamps as integers. Format them for the user's time zone only at the display layer. GMT (UTC+0) is the reference point. Once you accept that, conversion becomes a formatting exercise, not a time zone calculation.
Convert a Unix Timestamp to GMT: The Manual Formula
The math is boring and reliable. Here is the formula.
- Take the timestamp (seconds since the epoch).
- Divide by 86,400. The integer part is the number of days.
- Multiply the fractional part by 86,400 to get the seconds since midnight.
- Add both to 1970-01-01 00:00:00 UTC.
That result is GMT. No offset to add, no DST to worry about. GMT is fixed at UTC+0 year-round. The only time this changes is if you are converting to a location that observes daylight saving, which is a separate problem.
Worked Example
Take a timestamp representing 12:00 UTC on 19 January 2025.
Divide the timestamp by 86,400. The integer part gives the number of whole days since the epoch. Add those days to 1970-01-01. The result is 2025-01-19. The fractional part represents half a day: 12:00:00. Final output: 2025-01-19 12:00:00 UTC.
Use a Converter That Assumes UTC
Nobody does this by hand in production. Paste your Unix timestamp into a converter that assumes UTC, and you get the GMT time in ISO 8601 format, plus local time and a relative "time ago" display.
The reverse path also works: feed the tool a GMT date string, get the timestamp. That is useful when parsing logs or building API calls. The GMT output is always the same because GMT never changes.
Skip Converters That Ask for a Time Zone
Do not use a converter that asks you to select a time zone before processing a timestamp. A timestamp has no time zone. If a tool asks for "your time zone" before converting, it will produce the wrong answer unless you happen to be in UTC. Use one that assumes UTC for the input.
GMT Timestamp Traps That Break Code
These bugs are avoidable. You will encounter them eventually.
Adding an Offset to the Timestamp
The timestamp is already UTC. If you add your local offset before formatting, you double-shift. A timestamp that represents 12:00 UTC, when shifted by a New York offset of minus five hours, becomes 07:00 UTC. That is wrong. The timestamp represents an instant. The offset is a display concern.
Using Date() in JavaScript Without Specifying UTC
new Date(timestamp_in_milliseconds) creates a date in the local time zone. .toString() shows it in that local zone. Use .toISOString() to get the UTC/GMT string.
Confusing GMT with UK Local Time
The UK is not always on GMT. From late March to late October, the UK is on British Summer Time (BST), which is UTC+1. If you ask a UK server for "GMT" in July, you get the wrong answer unless the server is configured for UTC. Always specify "UTC" or "GMT" explicitly. Never say "London time."
ISO 8601 Format: The Standard for GMT Timestamps
Share a timestamp with another system using ISO 8601. The format is unambiguous: 2025-01-19T12:00:00Z. The Z suffix means "Zulu time," military shorthand for UTC/GMT. No offset, no ambiguity, no DST confusion.
The full format includes seconds and timezone: 2025-01-19T12:00:00Z or with milliseconds 2025-01-19T12:00:00.000Z. Some systems use +00:00 instead of Z. Both mean the same thing. The key is the Z. Without it, the string is ambiguous.
How to Store, Transmit, and Display
Store timestamps as integers. Transmit them in ISO 8601 with the Z suffix. Display them in the user's local time. Follow that order and time zone bugs disappear.
What Is the Year 2038 Problem?
A Unix timestamp is a 32-bit signed integer on many legacy systems. One second after 2038-01-19 03:14:07 UTC, the integer overflows and becomes negative.
This is the Year 2038 Problem. Any system still using 32-bit time storage will break on that date. The fix is to use 64-bit integers. If you are writing new code today, use a 64-bit timestamp. If you are maintaining legacy systems, this is your warning.
Which Systems Are at Risk
Most modern systems are 64-bit. Embedded systems, industrial controllers, and some old Unix machines are not. The next change coming is not a time zone shift. It is the integer overflow that will hit every 32-bit system on 2038-01-19 at 03:14:07 UTC. If you are converting timestamps today, the math is simple. In 2038, the math will be the least of your problems if you are still on 32-bit.