Date & Time Format Cheatsheet - Date Formatting & Timestamp Reference
Date bugs are usually timezone bugs — a timestamp that looks right locally is off by 8 hours elsewhere. Organized by strftime tokens, ISO 8601, timezones/offsets, per-language methods and timestamp conversion, this table lets you map a token to its output and avoid the classic UTC vs local pitfall. Use it when formatting logs, building API timestamps, or parsing ISO strings. After reading you pick a format that round-trips consistently across servers and clients.
Typical Use Case
For every developer who needs to express time correctly in code. This sheet covers four families: strftime placeholders (%Y/%m/%d and friends), ISO 8601 variants (with Z, with an offset, with milliseconds, week date, ordinal date, duration), the standard-library formatter in each language, and Unix timestamps with conversion in both directions. The hard part is never printing — it is timezone semantics: the same instant is two different strings in UTC and in local time, and IANA identifiers like America/New_York also carry daylight saving rules. Entries such as date -d @timestamp, Intl.DateTimeFormat and now + timedelta cover most formatting and arithmetic needs.
strftime Format Specifiers 13
%Y%y%m%d%H%I%M%S%p%A%B%Z%sISO 8601 Standard 7
2024-01-152024-01-15T10:30:00Z2024-01-15T10:30:00+08:002024-01-15T10:30:00.123Z2024-W03-12024-015PT1H30MTimezone & Offset 6
UTCGMT+08:00Asia/ShanghaiAmerica/New_YorkDSTDate Formatting by Language 7
new Date().toISOString()datetime.now().strftime("%Y-%m-%d")date("+%Y-%m-%d %H:%M:%S")SimpleDateFormat("yyyy-MM-dd")time.Now().Format("2006-01-02")chrono::Local::now()Intl.DateTimeFormat().format()Timestamp Conversion 6
Date.now()int(time.time())date +%snew Date(1705312200 * 1000)datetime.fromtimestamp(1705312200)date -d @1705312200Date Arithmetic 6
now + timedelta(days=7)new Date(Date.now() + 86400000)date -d "+1 days"d1 > d2(d2 - d1).daysdayjs(d1).isAfter(d2)Common Date Formats 5
2024-01-15 10:30:00Mon, 15 Jan 2024 10:30:00 GMT2024/01/15202401151705312200Parameter matrix
| Parameter | Effect | Example |
|---|---|---|
%Y / %m / %d / %H:%M:%S | compose a readable date out of strftime placeholders, the shell and C library idiom | date "+%Y-%m-%d %H:%M:%S" |
ISO 8601 with Z or an offset | carry timezone information in a machine-transferred string so instants survive timezones | 2024-01-15T10:30:00Z |
Unix timestamp | a plain integer naming one absolute instant, the easiest input for diffing and sorting | int(time.time()) |
timezone identifier | tie a wall-clock reading to an absolute instant; IANA names carry DST rules | America/New_York |
standard-library formatter | render one time value in each language without hand-rolled format strings | Intl.DateTimeFormat().format() |
date arithmetic and comparison | add days and compare order, after converting both sides to the same type | now + timedelta(days=7) |
Common pitfalls
SymptomThe same log line shows times several hours apart on the server and in the browser.
CauseOne side parses as UTC and the other as local time; a zone-less string like %Y-%m-%d is read as local.
FixStore UTC always (2024-01-15T10:30:00Z) and convert only in the view layer via toISOString() or an explicit IANA zone.
SymptomA string produced by "%Y-%m-%d" comes back from the backend with the date shifted.
Cause%Y-%m-%d is strftime syntax while ISO 8601 uses YYYY-MM-DD, and some backends parse the former as raw text.
FixAlways emit ISO 8601 with the capital T separator at the API layer and leave formatting to the client or a date library.
SymptomTimestamps stop lining up in March and November every year.
CauseThe timezone observes daylight saving time, so the offset changes with the date and a hardcoded 8-hour shift is off by an hour.
FixHand the work to a timezone library using Asia/Shanghai or America/New_York instead of computing offsets by hand.
SymptomAdding a fixed 24 hours to mean "one day later" lands an hour off on a DST switch day.
CauseA DST switch day is only 23 or 25 hours long, so fixed millisecond math disagrees with calendar arithmetic.
FixAdd by calendar semantics: now + timedelta(days=1) in Python, new Date(Date.now() + 86400000) in JS.
Troubleshooting
1Convert a Unix timestamp to a readable date and confirm the timezone
date -d @1705312200Prints the time in the machine timezone; diff it field by field against the string your API returns.
2Show the same instant in UTC and in local time side by side
date -u "+%Y-%m-%dT%H:%M:%SZ" && date "+%Y-%m-%dT%H:%M:%S%z"The gap between the two lines is exactly this machine timezone offset.
3Format a date in a specific timezone from JavaScript
new Intl.DateTimeFormat("en-US",{timeZone:"Asia/Shanghai"}).format(new Date())The name must be a valid IANA identifier; a wrong one throws a RangeError outright.
Command Examples
Turning a Unix timestamp into a readable UTC date
date -u -d @1705312200 '+%Y-%m-%d %H:%M:%S UTC'
date -u -d @1705312200 '+%Y-%m-%dT%H:%M:%SZ'The -u flag forces UTC interpretation; without it the output follows the machine local zone and the difference is invisible while you debug a timezone issue.
Output
2024-01-15 09:50:00 UTC 2024-01-15T09:50:00Z
One instant rendered in three time zones
python -c "
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
d = datetime.fromtimestamp(1705312200, tz=timezone.utc)
print('utc ', d.isoformat())
print('shanghai ', d.astimezone(ZoneInfo('Asia/Shanghai')).isoformat())
print('new york ', d.astimezone(ZoneInfo('America/New_York')).isoformat())
"All three strings denote the same instant and differ only in offset. America/New_York shows -05:00 here because January falls in standard time, not daylight saving time.
Output
utc 2024-01-15T09:50:00+00:00 shanghai 2024-01-15T17:50:00+08:00 new york 2024-01-15T04:50:00-05:00
Formatting a date in a chosen time zone from Node
node -e "
const ms = 1705312200000, d = new Date(ms);
console.log(d.toISOString());
console.log(new Intl.DateTimeFormat('en-US', { timeZone: 'Asia/Shanghai', dateStyle: 'long', timeStyle: 'short' }).format(d));
console.log(new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'long', timeStyle: 'short' }).format(d));
"toISOString() is always UTC while Intl.DateTimeFormat renders per the timeZone option. The eight-hour gap here is exactly the Asia/Shanghai offset.
Output
2024-01-15T09:50:00.000Z January 15, 2024 at 5:50 PM January 15, 2024 at 4:50 AM
Computing a day difference and adding a day
node -e "
const d1 = new Date('2024-01-15T00:00:00Z');
const d2 = new Date('2024-03-15T00:00:00Z');
console.log('days', (d2 - d1) / 86400000);
const d = new Date('2024-01-15T10:30:00Z');
console.log('plus1day', new Date(d.getTime() + 86400000).toISOString());
"Subtracting milliseconds yields a duration measured in days. For calendar arithmetic use Python timedelta(days=n), which carries calendar semantics.
Output
days 60 plus1day 2024-01-16T10:30:00.000Z
Common Pitfalls
- Never mix second and millisecond timestamps. Date.now() is 13 digits, a Unix timestamp 10, and the three-order-of-magnitude gap shifts dates wholesale.
- Store and transmit ISO 8601 with an explicit zone (Z or an offset) and convert to local time only for display, or server and browser readings will disagree.
- Do not substitute adding 24 hours for adding a day: a daylight-saving transition makes it 23 or 25 hours, and calendar semantics require a date library day arithmetic.
- %Y-%m-%d is a display format only. With no zone and no time it shifts by a full day when handed to a service that parses as UTC.
- IANA identifiers such as America/New_York carry daylight-saving rules; a hard-coded offset stands in for them and goes wrong by an hour twice a year.
Tips
- ISO 8601 is the international standard — use it consistently in APIs and databases.
- Go's reference time is 2006-01-02 15:04:05 (Mon Jan 2 15:04:05 MST 2006).
- Unix timestamp is seconds (10 digits); JavaScript Date.now() is milliseconds (13 digits).
- For timezones, store in UTC and convert to local only when displaying.
- Java's SimpleDateFormat is not thread-safe; use DateTimeFormatter in multithreaded code.
FAQ
Why is Date.now() 13 digits while a Unix timestamp is 10?
Different units. A Unix timestamp counts seconds, so 1705312200 is in seconds; Date.now() returns milliseconds, making the same instant 1705312200000. Mixing them shifts time by three orders of magnitude, landing dates near 1970 or tens of thousands of years out. The JS Date constructor takes milliseconds, so rebuilding an object from a seconds timestamp requires multiplying by 1000 first.
Why does one instant render differently on the server and in the browser?
Because local time is not an absolute instant. 2024-01-15T10:30:00+08:00 and 2024-01-15T02:30:00Z denote the same moment, yet rendering each in the local zone yields different strings. The fix is to store and transmit UTC with a Z or +00:00 designator and convert to local time only in the layer closest to the reader. The offset form of ISO 8601, such as +08:00, keeps both the absolute instant and the original offset intent, which makes it safer than bare local time.
What is wrong with implementing add one day as add 24 hours?
A day is not always 86400 seconds. On a daylight-saving transition, local midnight to the next midnight spans 23 hours in spring and 25 in autumn, so adding milliseconds yields a wall-clock reading off by an hour. To express a calendar day, use a date library day arithmetic — Python timedelta(days=1) has calendar semantics — or parse out the date part and advance it, rather than adding a duration.
Why does a %Y-%m-%d string so often get parsed off by a day?
It carries neither a time zone nor a time. %Y-%m-%d yields a day in some unspecified zone, and a service that parses it as UTC can shift it by a full day: a 2024-01-15 produced in UTC+8 read as UTC midnight appears as January 14 to a user in the US. Keep full ISO 8601 strings with a zone on every interface, and reserve %Y-%m-%d for display only — it is a rendering format, never a storage format.
When do I reach for the ordinal day (2024-015) or the week date (2024-W03-1)?
Both are ISO 8601 calendar representations for business logic that counts days within a year. The week date follows the ISO week-numbering rule where Monday starts the week and the week containing January 4 is week 1, so week numbers jump across a year boundary; the ordinal day simply numbers the year from 1 to 366. Weekly reports are easiest with the week date, while day counters align more naturally with array indices via the ordinal day. Neither is readable, so render YYYY-MM-DD for people regardless.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us