In modern web development, time is one of the most frequent sources of bugs. A user in Tokyo creates an order, the server is in Virginia, and the database is in Frankfurt. Without a strict protocol, a simple "Order Date" can morph into three different values. To build a scalable system, we must establish a "Single Source of Truth" for time data.
The Golden Rule: UTC for Transport, Local for Display
The industry standard for API communication is the Unix Timestamp (specifically, the 13-digit millisecond precision timestamp). Timestamps are timezone-agnostic integers representing an absolute moment in time.
Frontend to Backend
The frontend should send timestamps (e.g., 1779723000000). This removes ambiguity about string formats (ISO 8601 vs. others) and browser time zone settings.
const orderDate = new Date('2026-05-20T10:30:00+09:00');
const timestamp = orderDate.getTime(); // 1779723000000
fetch('/api/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderDate: timestamp })
});
Backend to Frontend
The backend should return timestamps. The frontend is then responsible for converting this integer into a human-readable string based on the user's browser settings.
{
"orderId": "ORD-2026-001",
"orderDate": 1779723000000,
"status": "confirmed"
}
// Frontend displays in user's local time
const date = new Date(response.orderDate);
console.log(date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}));
Handling "Date-Only" Logic
A specific challenge arises when the business requirement is "Date Only" (e.g., selecting a delivery day). If a user selects "May 20th" on their calendar, the frontend might generate a timestamp for May 20th, 00:00:00 in their local time.
If the backend blindly saves this timestamp, it introduces "time noise." A user in New York and a user in Beijing selecting the same calendar day will generate timestamps 12 hours apart.
The Problem
// User in New York (UTC-5)
const nyDate = new Date('2026-05-20T00:00:00-05:00');
console.log(nyDate.getTime()); // 1779480000000
// User in Beijing (UTC+8)
const bjDate = new Date('2026-05-20T00:00:00+08:00');
console.log(bjDate.getTime()); // 1779436800000
// Same calendar day, different timestamps!
The Backend Sanitization Layer
The backend must act as a sanitizer. It should not trust the exact millisecond sent by the client for date-based logic. Instead, implement a normalization step:
- Receive the timestamp from the client.
- Convert it to a date string using the business's target time zone (e.g.,
Asia/Shanghai). - Discard the time component entirely.
- Store the clean
YYYY-MM-DDstring (or UTC midnight) in the database.
Node.js Example
function sanitizeDateForStorage(timestamp, timeZone = 'Asia/Shanghai') {
// Convert timestamp to date string in target timezone
const dateObj = new Date(timestamp);
const dateStr = dateObj.toLocaleDateString('en-CA', {
timeZone: timeZone,
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
// dateStr is now "2026-05-20" - clean, no time component
return dateStr;
}
// Usage
const clientTimestamp = 1779480000000; // From New York user
const cleanDate = sanitizeDateForStorage(clientTimestamp);
console.log(cleanDate); // "2026-05-20"
Python Example
from datetime import datetime
import pytz
def sanitize_date_for_storage(timestamp_ms, timezone_str='Asia/Shanghai'):
# Convert milliseconds to datetime
dt_utc = datetime.utcfromtimestamp(timestamp_ms / 1000)
dt_utc = dt_utc.replace(tzinfo=pytz.UTC)
# Convert to target timezone
tz = pytz.timezone(timezone_str)
dt_local = dt_utc.astimezone(tz)
# Return date string without time component
return dt_local.strftime('%Y-%m-%d')
# Usage
client_timestamp = 1779480000000
clean_date = sanitize_date_for_storage(client_timestamp)
print(clean_date) # "2026-05-20"
Why Not Just Use Strings?
While passing ISO date strings (e.g., "2026-05-20") is readable, it is prone to parsing errors. Different browsers and libraries (like Moment.js or date-fns) may interpret a bare date string differently—some assume UTC, others assume local time.
// Different browsers may interpret this differently:
const date1 = new Date('2026-05-20');
// Some: 2026-05-20T00:00:00Z (UTC)
// Others: 2026-05-20T00:00:00+08:00 (Local)
The timestamp approach, combined with strict backend normalization, creates a "dumb pipe" for data transport and a "smart processor" on the server, ensuring data integrity across the entire stack.
Best Practices Summary
For Frontend
- Always send timestamps (milliseconds) to the backend
- Use
Date.getTime()orDate.now()for current timestamps - Only convert to local strings for display purposes
For Backend
- Never trust client-side date formatting for business logic
- Normalize all date-based inputs using explicit time zones
- Store "date-only" fields as
YYYY-MM-DDstrings or UTC midnight - Document your time zone conventions clearly
For Database
- Use appropriate data types:
DATEfor calendar dates,TIMESTAMPTZfor absolute moments - Always specify time zones in your database connections
- Consider storing business date separately from timestamp for reporting
Frequently Asked Questions
Should I use seconds or milliseconds for timestamps?
Milliseconds (13 digits) are preferred for JavaScript/web applications because Date.now() returns milliseconds. Seconds (10 digits) work for Unix command-line tools and some APIs.
What if my frontend users span multiple time zones?
Send timestamps from the frontend—they are timezone-agnostic. Let the backend normalize based on the business's target timezone, not the user's timezone (unless specifically required).
How do I handle "relative" dates like "next Monday"?
Calculate these on the frontend using the user's local timezone, send the resulting timestamp to the backend, and let the backend normalize it.
Conclusion
Establishing a strict protocol for time data is essential for building scalable, bug-free web applications. The key principles are:
- UTC timestamps for transport - Integers are unambiguous and timezone-agnostic
- Local time for display only - Let each client render in their own timezone
- Backend sanitization - Normalize all date inputs using explicit time zones
- Clean storage - Store "date-only" fields without time noise
By following this protocol, you can eliminate the most common time-related bugs in your application.
For more developer tools, explore our Timestamp Converter and JSON Formatter.