Unix Timestamp in JavaScript, Python, PHP, and Go — Code Reference
A Unix timestamp is the number of seconds since January 1, 1970, 00:00:00 UTC. Simple concept, consistent implementation — until you notice that JavaScript uses milliseconds instead of seconds, Python has multiple functions that return slightly different things, and PHP timestamps are affected by timezone settings in ways that catch people off guard.
The Unix Timestamp Converter handles quick conversions. This article is the code reference for when you need to work with timestamps programmatically in your language of choice.
JavaScript
JavaScript's Date.now() returns milliseconds, not seconds. This is the single most common source of timestamp bugs when a JS frontend talks to a backend API that expects seconds.
// Current timestamp in milliseconds
const ms = Date.now(); // e.g. 1712505600000
// Current timestamp in seconds (integer)
const secs = Math.floor(Date.now() / 1000); // e.g. 1712505600
// From a Date object
const d = new Date();
const secs2 = Math.floor(d.getTime() / 1000);
// Parse a Unix timestamp (seconds) into a Date
const ts = 1712505600;
const date = new Date(ts * 1000); // multiply by 1000 for ms
// Format to ISO 8601
const iso = date.toISOString(); // "2024-04-07T16:00:00.000Z"
// Get individual components (UTC)
const year = date.getUTCFullYear();
const month = date.getUTCMonth() + 1; // 0-indexed, add 1
const day = date.getUTCDate();
const hours = date.getUTCHours();
const minutes = date.getUTCMinutes();
// Convert a date string to a timestamp
const from_string = Math.floor(new Date("2024-04-07T16:00:00Z").getTime() / 1000);
Common pitfall: new Date(timestamp) without multiplying by 1000 will interpret a second-based timestamp as milliseconds, producing a date in 1970. Always multiply by 1000 when creating a Date from a seconds-based timestamp.
Token expiry: `js const expiresAt = Math.floor(Date.now() / 1000) + 86400; // 24 hours from now const isExpired = Math.floor(Date.now() / 1000) > expiresAt; `
Python
Python uses seconds by default. time.time() returns a float; use int() or // to get an integer.
import time
from datetime import datetime, timezone
# Current timestamp (seconds, float)
ts_float = time.time() # e.g. 1712505600.123456
# Current timestamp (seconds, integer)
ts_int = int(time.time()) # e.g. 1712505600
# Parse timestamp to datetime (UTC-aware)
ts = 1712505600
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
# datetime(2024, 4, 7, 16, 0, tzinfo=timezone.utc)
# Format to ISO 8601 string
iso = dt.isoformat() # "2024-04-07T16:00:00+00:00"
# Naive datetime (local time, avoid in production)
dt_local = datetime.fromtimestamp(ts)
# Convert datetime to timestamp
from datetime import datetime, timezone
dt = datetime(2024, 4, 7, 16, 0, 0, tzinfo=timezone.utc)
ts_back = int(dt.timestamp()) # 1712505600
# 24 hours from now
expires_at = int(time.time()) + 86400
Common pitfall: datetime.fromtimestamp() without tz=timezone.utc uses local system time. On a server in UTC this is fine; on a server in another timezone, or in user code, it introduces a timezone offset. Always pass tz=timezone.utc unless you explicitly want local time.
# Bad (timezone-dependent)
datetime.fromtimestamp(1712505600)
# Good (always UTC)
datetime.fromtimestamp(1712505600, tz=timezone.utc)
PHP
PHP's time() returns seconds, consistent with Unix convention. The most important thing to know: PHP date functions are affected by the date.timezone setting in php.ini. If that is wrong, formatted dates will be off.
<?php
// Current timestamp (seconds)
$ts = time(); // e.g. 1712505600
// Parse timestamp to formatted date (UTC)
echo date('Y-m-d H:i:s', $ts); // output depends on timezone setting
// Force UTC output regardless of php.ini
echo gmdate('Y-m-d H:i:s', $ts); // "2024-04-07 16:00:00"
// ISO 8601 (UTC)
echo gmdate('c', $ts); // "2024-04-07T16:00:00+00:00"
// Or manually:
echo gmdate('Y-m-d\TH:i:s\Z', $ts); // "2024-04-07T16:00:00Z"
// Convert date string to timestamp (UTC)
$ts2 = strtotime('2024-04-07 16:00:00 UTC');
// Using DateTime for more control
$dt = new DateTime('@' . $ts); // @ prefix means Unix timestamp
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('Y-m-d H:i:s');
// 24 hours from now
$expires_at = time() + 86400;
// Check if a timestamp has expired
$is_expired = time() > $expires_at;
Common pitfall: date() uses the local timezone from date.timezone. gmdate() always uses UTC. In a web application, use gmdate() for timestamps and API fields unless you have a deliberate reason to use local time.
PHP 8.x with DateTimeImmutable: `php $dt = new DateTimeImmutable('@' . $ts, new DateTimeZone('UTC')); echo $dt->format(DateTimeInterface::ATOM); // "2024-04-07T16:00:00+00:00" `
Go
Go's time package is clean and explicit about timezones. The zero value for time.Time is January 1, year 1 (not Unix epoch), so zero-value checks are different from other languages.
package main
import (
"fmt"
"time"
)
func main() {
// Current Unix timestamp (seconds)
ts := time.Now().Unix() // int64
// Current Unix timestamp (milliseconds)
ts_ms := time.Now().UnixMilli() // int64
// Current Unix timestamp (nanoseconds)
ts_ns := time.Now().UnixNano() // int64
// Parse Unix timestamp to time.Time (UTC)
t := time.Unix(1712505600, 0).UTC()
fmt.Println(t) // 2024-04-07 16:00:00 +0000 UTC
// Format to ISO 8601
iso := t.Format(time.RFC3339) // "2024-04-07T16:00:00Z"
// Parse ISO 8601 string to timestamp
parsed, _ := time.Parse(time.RFC3339, "2024-04-07T16:00:00Z")
ts2 := parsed.Unix() // 1712505600
// 24 hours from now
expires_at := time.Now().Add(24 * time.Hour).Unix()
// Check expiry
is_expired := time.Now().Unix() > expires_at
_ = ts
_ = ts_ms
_ = ts_ns
_ = ts2
_ = is_expired
fmt.Println(expires_at)
}
Key difference from other languages: Go's time.Unix(ts, 0) takes two arguments — seconds and nanoseconds. The nanoseconds parameter is almost always 0 for typical Unix timestamps.
Common pitfall: Forgetting .UTC() after time.Unix() means the time is in the local timezone of the machine. This is usually fine in production if the server is in UTC, but inconsistent across environments. Add .UTC() explicitly to be safe.
Comparing Timestamps Across Languages
| Task | JavaScript | Python | PHP | Go |
|---|---|---|---|---|
| Current timestamp (seconds) | Math.floor(Date.now()/1000) | int(time.time()) | time() | time.Now().Unix() |
| Default unit | Milliseconds | Seconds | Seconds | Seconds (also nano) |
| Parse timestamp to date | new Date(ts * 1000) | datetime.fromtimestamp(ts, tz=utc) | new DateTime('@'.$ts) | time.Unix(ts, 0).UTC() |
| Format to ISO 8601 | .toISOString() | .isoformat() | gmdate('c', $ts) | .Format(time.RFC3339) |
| Timezone default | UTC | System/local | php.ini setting | System/local |
Detecting Seconds vs Milliseconds
When you receive a timestamp and are not sure whether it is seconds or milliseconds:
- 10 digits: seconds (e.g. 1712505600 = April 2024)
- 13 digits: milliseconds (e.g. 1712505600000)
The boundary: any timestamp above 9,999,999,999 (10 billion) is likely milliseconds. The Unix timestamp in seconds exceeded 1,700,000,000 in September 2023 and will not reach 10,000,000,000 until November 2286.
The Unix Timestamp Converter detects the format automatically and shows both the seconds and milliseconds representation.


