MySQL Date and Time Types
Also Known As
MySQL DATETIME vs TIMESTAMP
MySQL date types
TIMESTAMP Y2038
MySQL time storage
TL;DR
DATETIME, TIMESTAMP, DATE, TIME, and YEAR — each with different ranges, timezone handling, and storage sizes.
Explanation
DATETIME stores date+time without timezone conversion (range: 1000-01-01 to 9999-12-31). TIMESTAMP stores as UTC and converts to the server timezone on retrieval (range: 1970-2038). TIMESTAMP auto-updates on row modification with DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. TIMESTAMP's 2038 problem is significant for long-lived data — use DATETIME for dates beyond 2038. Always store dates in UTC and convert for display in PHP.
Watch Out
⚠ TIMESTAMP columns hit Y2K38 on 2038-01-19 03:14:07 UTC — stored value wraps to NULL or 0 depending on strict mode.
Common Misconception
✗ TIMESTAMP handles timezones automatically so you don't need to think about them. TIMESTAMP converts using the MySQL server's timezone setting — if that changes, all stored timestamps display differently.
Why It Matters
TIMESTAMP columns silently hit Y2K38 — January 19, 2038, values wrap to 0. For data that will exist past 2038, DATETIME is required. Timezone confusion between DATETIME (no conversion) and TIMESTAMP (converted) causes display bugs.
Common Mistakes
- Using TIMESTAMP for birth dates or historical records — wraps at 2038.
- Relying on MySQL timezone conversion instead of storing UTC explicitly.
- Comparing DATETIME columns across different timezone servers and getting wrong results.
Avoid When
- Do not use TIMESTAMP for dates beyond 2038 — use DATETIME.
- Do not rely on MySQL's timezone conversion — set the application timezone explicitly and store UTC.
When To Use
- Use DATETIME for all date/time storage — store values in UTC, convert to local timezone in application code.
- Use DATETIME ON UPDATE CURRENT_TIMESTAMP for updated_at audit columns.
Code Examples
✗ Vulnerable
-- TIMESTAMP wraps at 2038-01-19 — don't use for long-lived data
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- Y2K38 problem
✓ Fixed
CREATE TABLE events (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
starts_at DATETIME NOT NULL, -- store in UTC
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;
// PHP: store in UTC, convert for display
$utc = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$stmt->execute([$utc->format('Y-m-d H:i:s')]);
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
31 Mar 2026
Views
12
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Google 4
Unknown AI 2
Perplexity 1
Ahrefs 1
Also referenced
How they use it
crawler 6
crawler_json 1
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Use DATETIME for flexibility and future-proofing, store values in UTC, handle timezone conversion in PHP
📦 Applies To
web
cli
🔗 Prerequisites
🔍 Detection Hints
TIMESTAMP column for created_at/updated_at on long-lived data
Auto-detectable:
✓ Yes
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: Low
Context: Line