Timezone-aware dates
Every date and time shown on DevPlace is displayed in your own timezone, automatically. You do not set a timezone anywhere: the page works it out from your browser and converts every timestamp to your local time. Two people in different parts of the world looking at the same post see the same moment, each in their own clock.
What you see
- Relative times such as
5m ago,3h ago, or2d agoare shown for anything recent and update on their own while the page is open. - After about a month, a relative time switches to an absolute DD/MM/YYYY date, shown in your local timezone.
- Hover over any time to see the full local date and time in a tooltip.
Because everything is anchored to a single universal instant, the conversion is exact: a message sent at 14:30 UTC shows as 15:30 for a reader in Central Europe and 09:30 for a reader on the US East Coast, with no configuration on either side.
How it works
DevPlace stores and sends every timestamp as UTC (Coordinated Universal Time) in the standard ISO 8601 format. The server never guesses your timezone. Instead, each timestamp is delivered to your browser as a machine-readable value, and a small piece of JavaScript reformats it to your local timezone using the browser's built-in internationalization support. The browser already knows its own timezone, so this needs no cookie, no header, and no account setting.
If JavaScript is disabled, you still see a sensible fallback date (the server-rendered text inside the element), so the page is never blank. With JavaScript on, that text is replaced by your local time the moment the page loads, and any times added later (a new message arriving, more posts loading as you scroll) are localized automatically.
For contributors
The mechanism is two Jinja globals plus one frontend module.
Server side. Use local_dt(iso, mode) or the relative-time shortcut dt_ago(iso) in templates. They emit a <time> element carrying the normalized UTC value and a server-rendered fallback:
<time datetime="2026-06-16T14:30:00+00:00" data-dt data-dt-mode="ago">3h ago</time>
mode is one of date (DD/MM/YYYY), datetime (DD/MM/YYYY HH:MM), or ago (relative). local_dt normalizes a naive timestamp to UTC, returns an empty string for empty input, and returns the raw value unchanged if it cannot be parsed.
Client side. static/js/LocalTime.js (reachable as app.localTime) finds every element marked data-dt, reformats its text to the browser's local timezone, and sets a full-datetime tooltip. A MutationObserver localizes any date inserted after load, and relative times refresh every 60 seconds. Frontend code that builds dates itself (for example the live message bubbles) creates the same data-dt element and the observer handles the rest.
When converting an existing display that used a precomputed relative string, keep a fallback so a missing field never blanks the date:
{{ dt_ago(item.created_at) if item.created_at else item.time_ago }}
What stays as plain text. The format_date() and time_ago() helpers remain plain-text functions for JSON API responses, the no-JavaScript fallback, and the few dates that must not be localized: user-entered calendar dates such as a project's release or demo date (which are plain DD/MM/YYYY values, not a specific instant), and any date placed inside an HTML attribute. Do not wrap those in local_dt.