-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Core Principle: Store UTC, Display Local
The golden rule is always store timestamps in UTC in your database, then convert to local timezones only at the presentation layer. This eliminates ambiguity and makes your data timezone-agnostic.
Best Practices for Your Architecture
1. Database Layer (MongoDB)
- Store all timestamps in UTC using ISO 8601 format with 'Z' suffix
- Use MongoDB's
ISODate()which automatically stores in UTC - Never store local times or timezone-naive timestamps
- Example:
2025-06-29T14:30:00.000Z(always UTC)
2. Application Logic Layer
- All business logic operates in UTC
- Convert user input to UTC immediately upon receiving it
- Perform all date calculations, comparisons, and sorting in UTC
- Only convert to local time when preparing data for display
3. User Interface Layer
- Always collect the user's timezone (detect via JavaScript or user preference)
- Convert UTC timestamps to user's local timezone for display
- When accepting user input, immediately convert local time to UTC
- Store user's timezone preference in their profile
4. LLM Processing Layer
- Send UTC timestamps to LLM providers
- Include timezone context in prompts when relevant: "Convert this UTC time to user's timezone (America/New_York)"
- Never rely on LLM providers to handle timezone conversion automatically
Implementation Strategy
Data Model
// User document
{
userId: "123",
timezone: "America/New_York", // Store user's timezone
createdAt: ISODate("2025-06-29T14:30:00.000Z"), // Always UTC
lastLoginAt: ISODate("2025-06-29T18:45:00.000Z") // Always UTC
}
// Event document
{
eventId: "456",
userId: "123",
scheduledAt: ISODate("2025-06-30T09:00:00.000Z"), // UTC
createdAt: ISODate("2025-06-29T14:30:00.000Z") // UTC
}Conversion Pattern
// Input: User schedules event for "2025-06-30 9:00 AM" in their timezone
const userTimezone = "America/New_York";
const userLocalTime = "2025-06-30T09:00:00";
// Convert to UTC for storage
const utcTime = moment.tz(userLocalTime, userTimezone).utc().toISOString();
// Result: "2025-06-30T13:00:00.000Z"
// Display: Convert UTC back to user's local time
const displayTime = moment.utc(utcTime).tz(userTimezone).format();
// Result: "2025-06-30T09:00:00-04:00"Fundamental Reasons Behind These Practices
1. Eliminates Ambiguity
UTC is unambiguous - there's no daylight saving time, no regional variations. "2025-06-29T14:30:00Z" means exactly one moment in time globally.
2. Enables Accurate Sorting and Comparison
When all timestamps are in UTC, database queries for date ranges, sorting by time, and temporal comparisons work correctly regardless of where your MongoDB instance runs.
3. Handles Daylight Saving Time Automatically
By storing UTC and converting at display time, you automatically handle DST transitions without data corruption or duplicate/missing hours.
4. Supports Global Users
A user in Tokyo and a user in New York can collaborate on the same data with timestamps that make sense to both, because conversion happens at display time.
5. Simplifies Business Logic
All your backend calculations (deadlines, durations, scheduling) work with a single, consistent time reference.
Common Pitfalls to Avoid
- Never store local times without timezone info - creates ambiguous data
- Don't rely on server timezone - your server location shouldn't affect user experience
- Don't convert timezones in database queries - keep queries simple, convert in application
- Don't assume LLM providers handle timezones correctly - always be explicit