I still pause for a second every time I need the current timestamp in a new language. Is it Date.now() or new Date().getTime()? time.time() or time.time? date +%s or date %s?

After enough Googling, I finally wrote down the commands I actually use. Here they are.

The Cheat Sheet

Language Seconds Milliseconds
JavaScript Math.floor(Date.now() / 1000) Date.now()
Python int(time.time()) int(time.time() * 1000)
Bash date +%s echo $(($(date +%s%N) / 1000000))

That table covers most real-world cases. The rest of this article explains the edge cases that trip people up.

JavaScript

JavaScript's Date API is built around milliseconds, which is both convenient and dangerous when your backend expects seconds.

// Milliseconds (Browser + Node.js)
Date.now();
// → 1720694400000

// The longer way
new Date().getTime();
// → 1720694400000

// The cursed way
+new Date();
// → 1720694400000

// Seconds (what most backends expect)
Math.floor(Date.now() / 1000);
// → 1720694400

One thing to watch out for: process.hrtime() in Node.js returns [seconds, nanoseconds] relative to process start, not a Unix timestamp. Use it for timing intervals, not for absolute time.

Date.now() works everywhere modern — IE9+, all current browsers, Node.js, Deno, Bun. There is no reason to use new Date().getTime() unless you are supporting something truly ancient.

Python

Python's time module returns seconds as a float with microsecond precision.

import time

# Seconds as float
ts = time.time()
print(ts)  # 1720694400.123456

# Seconds as integer
ts_int = int(time.time())
print(ts_int)  # 1720694400

# Milliseconds as integer
ts_ms = int(time.time() * 1000)
print(ts_ms)  # 1720694400123

If you prefer datetime:

from datetime import datetime, timezone

ts = datetime.now(timezone.utc).timestamp()
print(int(ts))  # 1720694400

Notice the timezone.utc argument. Without it, datetime.now().timestamp() uses the system timezone. If the server moves or the timezone changes, the same code can return a different number. time.time() avoids that entirely because it is always UTC-based.

Another common mistake: datetime.now() returns a naive datetime by default. Calling .timestamp() on a naive datetime uses the system timezone, which is a silent dependency on the environment.

Bash

For shell scripts, date +%s is the standard:

# Seconds
date +%s
# 1720694400

# Store in a variable
TIMESTAMP=$(date +%s)
echo $TIMESTAMP

Milliseconds in Bash is less elegant:

# Linux only (GNU date supports %N)
echo $(($(date +%s%N) / 1000000))
# 1720694400123

# macOS uses BSD date, which lacks %N
# Use Python or Node instead:
python3 -c 'import time; print(int(time.time() * 1000))'
node -e 'console.log(Date.now())'

date +%s is POSIX and works everywhere. %N is a GNU extension. If you need a cross-platform milliseconds snippet, lean on another language rather than fighting with date.

If you use this a lot, add aliases:

alias ts='date +%s'
alias tsms='echo $(($(date +%s%N) / 1000000))'

One-Liners for Other Languages

Sometimes you just need a quick answer:

// Go
time.Now().Unix()      // seconds
time.Now().UnixMilli() // milliseconds
# Ruby
Time.now.to_i                 # seconds
(Time.now.to_f * 1000).to_i   # milliseconds
<?php
time();                       // seconds
intval(microtime(true) * 1000); // milliseconds
// Rust
use std::time::{SystemTime, UNIX_EPOCH};

let ts = SystemTime::now()
    .duration_since(UNIX_EPOCH)
    .unwrap()
    .as_secs();

What to Memorize

If you only remember one thing per language:

  • JavaScript: Date.now() gives milliseconds
  • Python: int(time.time()) gives seconds
  • Bash: date +%s gives seconds

Everything else is a variation: divide by 1000, multiply by 1000, or cast to int.

When to Use Seconds vs Milliseconds

I default to seconds for anything that crosses a network boundary or gets stored in a database. It is the standard Unix timestamp unit, and almost every backend language expects it.

I use milliseconds only when:

  • I am passing the value directly to JavaScript's Date constructor
  • I need sub-second precision for logging or metrics
  • The API contract explicitly requires milliseconds

If you control the API contract, pick seconds and document it. Future maintainers will thank you.

A Real Debugging Scenario

Last year I was looking at two servers that disagreed on when an event happened. One logged 1720694400, the other logged 1720694400000. Both represented the same moment, but one system treated the value as seconds and the other as milliseconds.

The fix was not more code — it was a single line in the API documentation clarifying that all numeric timestamps were in seconds. Since then, I add a comment on every timestamp field I expose:

// Timestamp in seconds since Unix epoch

It takes five seconds and prevents hours of debugging.

Conclusion

Getting the current Unix timestamp is simple once you know the unit each language returns. The hard part is remembering whether you are dealing with seconds or milliseconds — and that is where most bugs come from.

For a quick visual check of the current timestamp in different units and time zones, the FastUnix Timestamp Converter shows everything in one place.