Time, dates and time zones
How apps handle time
Time is a fundamental part of most apps, but working with dates and times in a global, online environment comes with its own challenges. Computers don't understand human time zones, local calendars, or daylight saving time on their own. Instead, they store and process time in one consistent format that every system can refer to, wherever it is.
That format is called a timestamp. When your app saves a date and time, it's stored as a timestamp that isn't tied to any time zone, and it's only converted to local time when it's shown to a user. This lets users in different time zones work with the same data without confusion: the moment that was recorded stays the same, no matter where it's viewed from or whether daylight saving time has kicked in.
The challenge for app developers is that time has to be both absolute and context-aware. "3:00 PM" makes sense to a user in a given place, but your app needs to store it in a way that means the same moment to someone on the other side of the world.
Absolute and context-aware time
Calendar events are a good way to see this in action. Say you schedule a meeting in a calendar app such as Google Calendar, Apple Calendar, or Outlook while you're in New York. You set it for 3:00 PM ET, and that's when it appears in your calendar.
If you later travel to Los Angeles, your calendar app may offer to adjust to the local time zone. If you accept, the same meeting now shows as 12:00 PM PT. The meeting itself hasn't changed: it still happens at the same moment. Only the way it's displayed has changed to match where you are.
That's what it means for time to be absolute, in that it's one fixed moment worldwide, and context-aware, in that it's shown in the viewer's local time zone. Calendar apps handle this for you, and Bubble does too.
Quick facts about dates and times in Bubble
Dates always include a time
Bubble always saves a date and a time together, as most computer systems do. You can't save just one, but there are workarounds.
Dates are stored as Unix time
Each value is stored as the number of milliseconds since January 1, 1970, 00:00:00 UTC.
Dates are shown in the user's time zone
Bubble converts dates to the user's local time zone when displaying them, unless you've set a time zone override.
The server uses UTC by default
On the server, Bubble uses UTC if the user's time zone isn't available and no time zone override is set.
Daylight saving time changes UTC offsets
Regions that observe daylight saving time switch between two UTC offsets during the year. Eastern Time (ET), for example, is UTC-5 in winter and UTC-4 in summer, so the difference between two places can change with the season.
Date and time inputs use local time
Date and time pickers use the user's local time zone, unless you've set a time zone override.
Unix time explained
To keep time consistent, Bubble stores dates in Unix time, a widely used standard that counts the milliseconds since January 1, 1970, at 00:00:00 UTC. That starting point is known as the Unix epoch.
Unix time is simple, it counts upward at a steady rate, and it has no time zone. A Unix timestamp always refers to the same moment, wherever the user is. That makes it easy for systems to compare, sort, and calculate with dates.
For example, the timestamp 1,700,000,000,000 is the moment 1.7 trillion milliseconds after the Unix epoch, which is November 14, 2023, at 10:13 PM UTC.
Every date and time in your Bubble database is stored this way. When a date is shown to a user, Bubble converts it to their time zone, so each user sees the right local time.
Because Unix time is so widely used, it also makes it easier for your Bubble app to exchange dates with other apps and systems, since they're all "speaking the same language."
Time zones
Time zones exist so that clock time lines up with daylight in different parts of the world. Because the sun rises and sets at different times around the globe, time zones let people in each region keep a schedule that makes sense locally.
Each time zone is defined by its offset from UTC, such as UTC-5 for Eastern Time in winter or UTC+1 for Central European Time (CET). Some regions also observe daylight saving time (DST), which shifts local time by one hour for part of the year.
For app developers, time zones add complexity when users are spread around the world. Here's how a single timestamp is displayed in different places in winter:
UTC
10:00 AM
Los Angeles
2:00 AM
New York
5:00 AM
Paris
11:00 AM
Because the stored value doesn't change, the conversion happens on the fly, based on each user's time zone.
Users expect times to make sense to them. If someone books a meeting for 3:00 PM, they assume it's 3:00 PM where they are, while a colleague in another time zone might see the same meeting at 9:00 PM. Without proper time zone handling, appointments can show up at the wrong time, and scheduled notifications can go out at unexpected hours.
Most modern apps detect the user's time zone from their device settings and adjust times automatically. Some situations call for a fixed time zone instead.
When to override time zones
By default, Bubble shows dates in the time zone reported by the user's browser. That's usually the time zone the user is actually in, and it updates if they travel and reload the page.
Some apps, though, need a fixed time zone that stays the same no matter where the user is:
Flight and travel booking
Users usually expect times to be shown in the time zone where the trip or event takes place. If you're in Oslo booking a tour in Tokyo, it's most helpful to see the tour time in Tokyo time.
Event management
Conferences and in-person events often use one fixed time zone, so every participant sees the same time. For online events, users may prefer to see the time in their own time zone, since that's where they'll join from.
Work shift scheduling
Global businesses may schedule shifts in the time zone of their headquarters, to keep things consistent across locations.
In these cases, you can set a time zone explicitly. Bubble then uses that time zone instead of converting to each user's local time, so everyone sees the same time.
Overriding time zones
Bubble's timezone override controls let you choose which time zone your app uses to interpret and display dates, instead of the user's local time zone. This can be useful for scheduling, financial transactions, or logs, where everyone needs to see the same reference time.
Enabling timezone override controls
Where you can override the time zone
Date/time inputs
Controls the time zone that date and time pickers use to interpret and display values. Every user picks and sees times in the same time zone, which is useful when a meeting time should read the same for everyone.
Pages
Applies a fixed time zone to the whole page. Every date on the page uses that time zone instead of each user's local time, which is useful for dashboards and reports that need to look the same for every user.
Backend workflows
Applies to date calculations inside the workflow. It doesn't change the time zone used to schedule the workflow itself (see below).
Backend workflows need a bit of extra care. If a backend workflow runs a date calculation, the override applies to that calculation. But if the workflow schedules another workflow to run at a specific time, that time is still set in the time zone of the original request.
If you don't use a time zone override, a backend workflow scheduled from a page uses the page's time zone, which is the time zone reported by the user's browser.
Using timezone overrides well
Before you set a time zone override, think about:
How your users expect to see and enter times. Should an event's start time be shown in each user's local time, or in a fixed business time zone?
Whether the override affects workflows, such as scheduled notifications or API calls that depend on exact timing.
Testing a range of scenarios, to confirm the override works as expected for users in different locations. See Testing other time zones in your browser below.
Storing only a date or only a time
Since every date in Bubble includes a time, you need a workaround if your app only cares about one of them. There are two common approaches: storing the value in a date field with a fixed time or date, or storing its parts in separate fields.
A date field
Moments in time, and anything that needs date math, like adding days, comparing dates, or calendar elements
Time zones affect how the value is displayed, so you need to store and display it in the same time zone.
Separate fields
Dates that should read the same everywhere, like birthdays, anniversaries, and holidays
Date operators don't work on number fields, so you combine the fields yourself to display or calculate with them.
Using a date field
Only a date
Store the date at midnight UTC (00:00 UTC), and display it in UTC with a format that leaves out the time.
Only a time
Store the time on a fixed reference date, such as January 1, 1970, and display it with a format that leaves out the date. Use the same time zone when you store the value and when you display it.
The time zone you display the value in matters. If you store a date at midnight UTC but display it in each user's local time zone, users west of UTC see the evening before, so the date appears one day early. Display date-only values in the same time zone you stored them in, such as UTC.
To control how a date is displayed, use the :formatted as operator. It converts the date to text in the format you choose, such as only the date or only the time, while the stored value stays the same.
Using separate fields
Some dates aren't really moments in time. A birthday on May 14 is May 14 wherever the person is, and it shouldn't turn into May 13 because someone looks at it from another time zone. The same goes for anniversaries, holidays, and other dates that belong to the calendar rather than to a specific moment.
For these, you can skip the date field type and store each part of the date in its own field. Here's what that could look like for a birthday on the User data type:
Birth day
number
14
Birth month
number
5
Birth year
number
1990
Since these are plain numbers, no time zone is involved. Every user sees the same values, and nothing shifts by a day. If your app doesn't need to know the year, such as for a birthday reminder, you can leave the Birth year field out.
The same idea works for times. For opening hours, for example, you can store Hour and Minute as two number fields, so 9:30 reads as 9:30 for every user.
Setting up a birthday field
Collect the values
The simplest option is to give the user three inputs, such as dropdowns for the day and month and a number input for the year. Since the user picks each part directly, time zones never come into play.
If you'd rather use a date picker, you can pull out each part of its value with the :extract operator. The picker's value is in the user's time zone, so extracting it on the page gives you the date they picked. For the day, choose the option that returns the day of the month, not the day of the week.
Finding today's birthdays
To find users who have a birthday today, add two constraints to a Do a search for Users:
Birth month =
Current date/time:extract monthBirth day =
Current date/time:extract day
Current date/time is evaluated in a time zone too. On a page, that's the user's time zone, but in a backend workflow it's UTC unless you've set a time zone override. If you send birthday messages from a scheduled backend workflow, users far from UTC may get theirs a few hours early or late.
Calculating age
Separate fields don't support date operators, but you can still work out someone's age. Subtract Birth year from the current year, then subtract one more if their birthday hasn't happened yet this year, meaning the current month is before Birth month, or it's the same month and the current day is before Birth day.
If your app does a lot of date math with these values, it can be easier to store a date field alongside the separate fields and use each one where it fits best.
Testing other time zones in your browser
When your app works with dates, it's useful to see how it behaves for users in other time zones. Some browsers let you override the time zone in their developer tools, without changing your computer's settings. This is especially handy for testing scheduling features and time-sensitive logic.
Chromium-based browsers
Chrome, Edge, Brave, Vivaldi, and other browsers built on Chromium share the same developer tools, so the steps are the same in all of them.
Firefox and Safari
Firefox and Safari don't have a built-in way to override the time zone in their developer tools:
Firefox
Turning on privacy.resistFingerprinting in about:config makes Firefox report every time zone as UTC to reduce tracking. You can't use it to choose a specific time zone.
Safari
Safari uses your computer's time zone. To test another time zone, you'll need to change it in your system settings.
More advanced methods, such as browser extensions or automation tools, can change the time zone in these browsers too, but they're outside the scope of this article.
FAQ: Time, dates, and time zones
General questions
Backend workflows and time zones
Last updated
Was this helpful?