"The timestamp I see on the server — why is it always 8 hours off when I convert it to Beijing time?"
This question shows up in developer communities with absurd frequency. Some suspect the timestamp itself is wrong, others blame the conversion tool, but in the vast majority of cases the problem is a misunderstanding of timezones. This article lays out the relationship between Unix timestamps and timezones in one place.
Unix Timestamps Are Always UTC — This Is the Premise for Everything
The definition of a Unix timestamp: the number of seconds (or milliseconds) elapsed from 1970-01-01 00:00:00 UTC to the target moment.
Note the keyword: UTC. A timestamp carries no timezone information — it represents an absolute point in time. The timestamp 1721900000 is late afternoon on July 25, 2024 in Beijing, early morning the same day in New York, and mid-morning in London — but the numeric value is always the same.
The so-called "8-hour offset" boils down to:
- China uses UTC+8 (East 8th timezone)
- When you treat a UTC timestamp "as local time" for display, or conversely generate a timestamp by treating local time "as UTC," you get exactly an 8-hour skew
// A Unix timestamp (seconds)
const ts = 1721900000;
// Correct: JavaScript Date displays in the local timezone automatically
const date = new Date(ts * 1000); // JS uses milliseconds
console.log(date.toString());
// In a UTC+8 environment: "Thu Jul 25 2024 17:33:20 GMT+0800"
// In a UTC environment: "Thu Jul 25 2024 09:33:20 GMT+0000"
// Same timestamp, different machines show different times — but the timestamp itself hasn't changed
Three Most Common "Off by 8 Hours" Scenarios
Scenario 1: Server Formats in UTC, Frontend Displays Directly
Many backend services (especially cloud-deployed ones) default to UTC. If the backend returns a formatted string instead of a timestamp:
# Python backend (server timezone is UTC)
from datetime import datetime
now = datetime.utcnow()
print(now.strftime('%Y-%m-%d %H:%M:%S'))
# Output: 2024-07-25 09:33:20 (UTC time)
The frontend receives "2024-07-25 09:33:20" and displays it directly — Chinese users see a time "8 hours short."
Fix: Have the backend always return timestamps or ISO 8601 format (with timezone identifier), and let the frontend handle localized display:
# Recommended: return ISO format with timezone
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
print(now.isoformat())
# "2024-07-25T09:33:20+00:00" —— the frontend can parse this correctly
Scenario 2: JavaScript new Date() Parsing a String Without Timezone
// This string has no timezone info
const str = '2024-07-25 09:33:20';
// Most browsers parse it as local time (UTC+8)
const d1 = new Date(str);
console.log(d1.getTime() / 1000); // The resulting timestamp corresponds to UTC 01:33:20
// If the backend considers this UTC, you're 8 hours off
// Correct approach: specify the timezone explicitly
const d2 = new Date('2024-07-25T09:33:20Z'); // Z means UTC
const d3 = new Date('2024-07-25T09:33:20+08:00'); // explicitly East 8th
Scenario 3: Database Storage and Read Timezone Mismatch
MySQL's TIMESTAMP type converts based on the connection's time_zone variable, while DATETIME does no conversion. If your app server is in UTC but the database is configured as +08:00, writes and reads can drift by 8 hours.
-- Check the current session timezone
SELECT @@session.time_zone;
-- Set it to UTC uniformly
SET time_zone = '+00:00';
Timezone Handling Notes per Language/Library
| Environment | What to Watch For |
|------|----------|
| JavaScript Date | Internally stores UTC ms; toString() outputs in local timezone, toISOString() outputs UTC |
| dayjs | Uses local timezone by default; needs dayjs.tz plugin for other zones |
| moment | moment() is local, moment.utc() is UTC, moment.tz() specifies a zone |
| Python datetime | naive datetime has no timezone; always use datetime.now(timezone.utc) |
| Java Instant | Instant.now() is always UTC; convert to local with ZonedDateTime |
| Go time | time.Now() carries local Location; time.Unix() returns local-zone time |
// dayjs handling timezone conversion correctly
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
const ts = 1721900000;
// Timestamp → Beijing time
const beijing = dayjs.unix(ts).tz('Asia/Shanghai');
console.log(beijing.format('YYYY-MM-DD HH:mm:ss'));
// "2024-07-25 17:33:20"
// Timestamp → UTC
const utcTime = dayjs.unix(ts).utc();
console.log(utcTime.format('YYYY-MM-DD HH:mm:ss'));
// "2024-07-25 09:33:20"
Best Practices to Avoid Timezone Issues
- Standardize on UTC for storage and transport: Store UTC in the database; return UTC timestamps or ISO strings with a
Zsuffix from APIs. - Only convert timezones at the presentation layer: The frontend converts display based on the user's timezone (
Intl.DateTimeFormat().resolvedOptions().timeZone). - Never assume the server timezone: Set it explicitly at app startup rather than relying on the system default.
- Avoid naive datetime: Every datetime object should carry timezone information.
If you just want to quickly check what a timestamp corresponds to in a given timezone — or convert a time in some timezone back to a timestamp — use the Timestamp Converter to see it directly. It supports multi-timezone comparison, and all calculations happen locally in your browser with no data sent to any server — which is especially reassuring when you're troubleshooting production timestamps.
相关文章
Online Word Counter: Count Words, Characters, Lines Instantly
Learn how to use an online word counter to count words, characters, lines, and paragraphs. Understand Chinese vs English counting differences and use cases in writing and development.
UUID Generator: Complete Guide to Unique Identifiers (UUID, NanoID, ULID)
Understand UUID v4, NanoID, and ULID fundamentals. Learn how to use an online UUID generator, and discover best practices for databases, distributed systems, and API tracking.
Online User-Agent Parser: Identify Browser and Device Information
Learn how to parse User-Agent strings. Understand browser, operating system, and device type identification methods, and applications in data analytics and compatibility testing.