Reminder on timezones and saving datetime

Datetimes formatted as ISO will always return UTC (ends with Z)

It’s important to note that formatting as other than ISO will use the user/browser’s timezone. This includes extracting hours and minutes. It extracts values as of the user/browser timezone.

Unless you have some overrides playing monkey somewhere.

So take note when constructing your APIs. It’s all fun and games until a user comes to an event 8 hours after it starts. Not saying it happened to any of mine but it could…

Best is to always store datetime in UTC (Bubble already does this by default). I do the same for any external DBs with dates. I just let Bubble handle the timezone rendering.

Good reminder. One detail to note is that Bubble does not actually store a datetime “in UTC” as a timezone-bearing value. It stores a specific moment in time, without any timezone attached. Timezone only affects how that moment is interpreted, entered, extracted, rounded, and displayed.

By default, Bubble shows and extracts date components based on the timezone reported by the user’s browser. However, as you mentioned, this default can be changed at several levels: formatting, extraction, date inputs, page settings, and backend processing can all use specific timezone overrides. Therefore, extract hour, extract date, or standard formatting should not be assumed to use the browser’s timezone once an override is set. On the server side, the defaults also change: a workflow triggered without a browser (for instance, via Bubble’s API) performs its date calculations in UTC, and scheduled workflows remember the timezone from when they were set up.

Bubble’s simplified ISO / JSON-safe representation is UTC and ends with Z:

2026-07-15T14:30:00.000Z

ISO 8601 can also show an explicit offset — this represents the same moment:

2026-07-15T10:30:00-04:00

When working with APIs, always send either Z or a specific offset. A datetime string without timezone information is unclear and may be interpreted differently by the browser, backend, or receiving service. Bubble’s API provides dates in a UTC ISO format.

It is helpful to distinguish three different concepts:

  1. Absolute instant — a unique moment in time, like the start of a live event. Store it as a Bubble date; Bubble will keep the same moment for every user.

  2. Civil date or calendar identity — a value like “July 15” or “July 2026”. This doesn’t necessarily refer to a moment. Birthdays, unavailable calendar days, billing months, and all-day selections may need a different representation, such as year/month/day fields, a YYYYMMDD key, or a month serial. Saving them only as midnight can cause another timezone to show the previous or next calendar day.

  3. Local scheduling rule — a rule like “every Monday at 9:00 AM in New York”. Storing just the first UTC timestamp isn’t sufficient: keep the local time, the IANA timezone (for example, America/New_York), and the recurrence rule. The UTC offset can change because of daylight-saving rules, while the intended local time stays at 9:00 AM.

For a one-time scheduled event, a helpful model is:

StartAt: date
EndAt: date
TimezoneID: text (IANA, e.g. America/New_York)

StartAt and EndAt specify exactly when the event happens. TimezoneID maintains the civil context in which it was scheduled and allows the event to be displayed consistently in its location’s timezone (Bubble’s formatting override accepts a dynamic timezone value, so this field can directly influence the display).

One more point: a date-only input is still stored by Bubble as both a date and a time — usually midnight in the timezone used by the input. It should not automatically be seen as a timezone-independent calendar date.

So the broader guideline is:

Real-world moment → store an absolute Bubble dateEvent location / context → also store an IANA TimezoneIDCalendar-only identity → store civil components or a civil keyRecurring local schedule → local time + TimezoneID + recurrence ruleAPI datetime → ISO with Z or an explicit offset

Let Bubble store absolute moments, but be clear about which timezone to use whenever you convert between those moments and human calendar values.

Wall of text…

Bubble just (most likely) stores dates in UNIX, which is basically UTC. You can tell cause it gets passed as a date object to the browser.

Edit:
Ah I just remembered it’s PostGres.