# How to handle time zone differences in Bubble.io workflows: Step-by-Step Guide

- Tool: Bubble
- Difficulty: Intermediate
- Time required: 20-25 min
- Compatibility: Growth plan+ (requires backend workflows)
- Last updated: March 2026

## TL;DR

Bubble stores all dates in UTC, but backend workflows that schedule tasks or send notifications must account for each user's local time zone. This tutorial shows you how to store user time zones, convert UTC to local time in workflow logic, and handle daylight saving transitions so your scheduled workflows fire at the right moment for every user.

## Overview: Handling Time Zone Differences in Bubble Workflows

When you schedule backend workflows — such as daily reminders, recurring billing, or timed notifications — the server runs in UTC. If a user in New York expects a reminder at 9 AM EST, your workflow must calculate the correct UTC offset. This tutorial walks through capturing user time zones, storing offsets, and building workflow logic that converts times correctly even during daylight saving changes.

## Before you start

- A Bubble app on the Growth plan or higher (backend workflows require a paid plan)
- Basic familiarity with Bubble's Workflow tab and backend workflows
- Understanding of the Data tab for creating fields
- At least one existing Data Type (User) in your app

## Step-by-step guide

### 1. Add a timezone field to your User data type

Open your Bubble editor and navigate to the Data tab. Click Data types in the sub-menu. Select the User data type. Click Create a new field. Name it timezone and set the type to text. This field will store a value like America/New_York or Europe/London. Save the field. Then create a second field called utc_offset of type number — this stores the numeric offset in hours (e.g. -5 for EST).

> Pro tip: Use IANA timezone names (America/New_York) rather than abbreviations (EST) because abbreviations do not account for daylight saving time automatically.

**Expected result:** Your User data type now has a timezone (text) field and a utc_offset (number) field.

### 2. Detect and save the user's timezone on login

Go to the Design tab and open the page where users land after login. Add a workflow triggered by the Page is loaded event. Add an Only when condition: Current User's timezone is empty. As the first action, choose Plugins → Run JavaScript (requires the Toolbox plugin). In the script, enter: bubble_fn_timezone(Intl.DateTimeFormat().resolvedOptions().timeZone). Then add a second action: Account → Make changes to current user. Set timezone to the result of the JavaScript step. Set utc_offset to Current Date/Time:extract hours — Current Date/Time:formatted as custom (UTC):extract hours.

> Pro tip: Install the free Toolbox plugin from the Bubble Plugin marketplace to use Run JavaScript in workflows.

**Expected result:** When a user loads the page and has no timezone saved, Bubble detects their browser timezone and saves it to their User record.

### 3. Create a backend workflow that schedules in local time

Navigate to the Workflow tab and click the Backend workflows link at the bottom of the Pages dropdown. Create a new backend workflow called send_local_reminder. Add two parameters: user (type User) and reminder_time (type date). In the workflow, add a Send Email action. For the scheduled time of this workflow, use the formula: reminder_time +(hours): user's utc_offset * -1. This converts the user's desired local time into UTC so the workflow fires at the correct moment.

> Pro tip: Always multiply the offset by -1 when converting from local to UTC. For example, UTC-5 means you add 5 hours to get UTC.

**Expected result:** A backend workflow that accepts a user and a desired local time, then schedules email delivery at the corresponding UTC time.

### 4. Schedule the workflow from the frontend

Go back to a frontend page and create a button labeled Set Reminder. Add a workflow triggered by When Button Set Reminder is clicked. Add an action: Schedule API Workflow. Select send_local_reminder. Set user to Current User. Set reminder_time to the date/time the user selected (from a date picker on the page). Bubble will use the backend workflow's offset logic to convert the time to UTC before scheduling.

**Expected result:** Clicking the button schedules the backend workflow to run at the correct UTC time matching the user's local time.

### 5. Handle daylight saving time transitions

Daylight saving changes shift UTC offsets by one hour twice a year. To handle this, create a recurring backend workflow called update_user_offsets that runs daily at midnight UTC. In this workflow, use the Schedule API Workflow on a list action targeting all users. For each user, recalculate utc_offset by comparing the current server UTC time with the user's local equivalent using their stored IANA timezone. Update the utc_offset field accordingly. This keeps offsets current even when clocks change.

> Pro tip: Run the offset recalculation a few days before known DST transitions (second Sunday of March and first Sunday of November in the US) to ensure accuracy.

**Expected result:** User UTC offsets update automatically so scheduled workflows continue firing at the correct local time year-round.

### 6. Display dates in the user's local time zone on the frontend

On any page that shows dates, Bubble automatically displays them in the user's browser timezone. However, if you need to show another user's local time — for example, a meeting participant's availability — use a text element with a dynamic expression: Meeting's start_time +(hours): Meeting's host's utc_offset :formatted as hh:mm A. This converts the stored UTC time to the host's local time for display.

**Expected result:** Dates and times display correctly in each user's local time zone, even when viewing other users' scheduled events.

## Complete code example

File: `Workflow summary`

```text
TIME ZONE HANDLING — WORKFLOW SUMMARY
=====================================

DATA SETUP
  User Data Type:
    - timezone (text): e.g. "America/New_York"
    - utc_offset (number): e.g. -5

FRONTEND WORKFLOW: Detect User Timezone
  Trigger: Page is loaded
  Only when: Current User's timezone is empty
  Step 1: Run JavaScript → Intl.DateTimeFormat().resolvedOptions().timeZone
  Step 2: Make changes to Current User
    - timezone = Result of step 1
    - utc_offset = (local hour difference from UTC)

BACKEND WORKFLOW: send_local_reminder
  Parameters:
    - user (User)
    - reminder_time (date)
  Schedule time calculation:
    reminder_time +(hours): user's utc_offset * -1
  Step 1: Send Email to user's email
    - Subject: "Your scheduled reminder"
    - Body: dynamic content

FRONTEND WORKFLOW: Schedule a Reminder
  Trigger: Button "Set Reminder" is clicked
  Step 1: Schedule API Workflow → send_local_reminder
    - user: Current User
    - reminder_time: DatePicker's value

BACKEND WORKFLOW: update_user_offsets (Recurring Daily)
  Trigger: Scheduled, runs every 24 hours at 00:00 UTC
  Step 1: Search for Users (all)
  Step 2: Schedule API Workflow on a list
    - Recalculate utc_offset for each user
    - Based on IANA timezone + current DST status

DISPLAY FORMULA (Frontend)
  Meeting time in host's zone:
    Meeting's start_time +(hours): Meeting's host's utc_offset
    :formatted as hh:mm A
```

## Common mistakes

- **Using timezone abbreviations instead of IANA names** — Abbreviations like EST or PST do not account for daylight saving time. EST is always UTC-5, even during summer when Eastern time is actually UTC-4 (EDT). Fix: Store IANA timezone identifiers like America/New_York which automatically resolve the correct offset for any date.
- **Forgetting that Bubble stores all dates in UTC** — If you schedule a workflow for '9:00 AM' without converting, it runs at 9:00 AM UTC — not the user's local 9:00 AM. Fix: Always apply the UTC offset conversion when scheduling backend workflows: desired_local_time +(hours): utc_offset * -1.
- **Not updating offsets when daylight saving time changes** — A static offset of -5 for New York becomes wrong in summer when the offset shifts to -4. Fix: Create a recurring daily backend workflow that recalculates each user's utc_offset from their stored IANA timezone.
- **Performing timezone math on the frontend for server-scheduled tasks** — Frontend calculations depend on the browser's clock, which may be wrong. Backend workflows need UTC-based scheduling. Fix: Do all scheduling math in backend workflows where you control the UTC reference point.

## Best practices

- Always store dates in UTC in your database and convert only for display or scheduling
- Use IANA timezone identifiers (America/New_York) instead of abbreviations (EST/EDT)
- Recalculate UTC offsets daily with a recurring backend workflow to handle DST transitions
- Test your scheduling logic with users in multiple time zones before going live
- Use Bubble's built-in date formatting for frontend display — it auto-adjusts to browser timezone
- Store the utc_offset as a number field for easy arithmetic in workflow expressions
- Log scheduled workflow times alongside the target user's timezone for debugging

## Frequently asked questions

### Does Bubble store dates in UTC or the user's local time?

Bubble stores all dates in UTC on the server. On the frontend, Bubble automatically converts dates to the user's browser timezone for display. Backend workflows always operate in UTC.

### How do I detect a user's timezone in Bubble?

Use the Toolbox plugin's Run JavaScript action with Intl.DateTimeFormat().resolvedOptions().timeZone. This returns the IANA timezone string (e.g., America/New_York) which you can save to a text field on the User data type.

### Will my scheduled workflows break during daylight saving time changes?

Yes, if you use a static UTC offset. To prevent this, store the IANA timezone name and recalculate the numeric offset daily with a recurring backend workflow.

### Can I schedule a workflow to run at 9 AM in every user's local time?

Not with a single scheduled workflow. You need to schedule individual workflows per user, each offset by their UTC difference so the workflow fires at their local 9 AM.

### What is the difference between timezone and utc_offset fields?

The timezone field stores the IANA identifier (America/New_York) which never changes. The utc_offset stores the current numeric offset (-5 or -4) which changes with daylight saving time. You need both for accurate scheduling.

### Can RapidDev help with complex timezone logic in my Bubble app?

Yes. RapidDev's engineering team can architect timezone-aware scheduling systems, including DST handling, multi-timezone displays, and recurring workflow optimization for apps with users worldwide.

### Does the Toolbox plugin cost anything?

No. The Toolbox plugin is free and is one of the most commonly used Bubble plugins. It adds JavaScript execution, expression evaluation, and other developer utilities to your app.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/handle-time-zone-differences-bubble-workflows
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/handle-time-zone-differences-bubble-workflows
