Quickbase Automation Developer Lab · Lesson 18
Dates, Time, and Scheduling
A record can enter a different business state because the clock moved—even when nobody edited the record. In this lab we investigate Quickbase Date/Time values, UTC, duration arithmetic, runtime time, relationship dates, business-rule precedence, and scheduled reevaluation.
Before You Begin
Start Lesson 18 with fresh data and a fresh Pipeline
Lesson 18 uses a new set of Tasks and Projects created specifically for experimenting with dates and time. Download both CSV files and use them to prepare the tables for this lesson.
The Tasks data contains 15 records with deliberately different Due Date and Date Completed values. These include durations below, at, and above our three-hour boundary, records that cross midnight, records without completion dates, and Tasks related to Projects with different target dates.
The Projects data contains four parent Projects with different Target Dates. We will use the relationship between Projects and Tasks later in the lesson to compare a Task's Due Date with its Project's Target Date.
Leave your Lesson 17 Pipeline alone.
Create a new Pipeline for Lesson 18. The previous Pipeline is evidence of what you learned in Lesson 17 and should remain available as a working reference. Lesson 18 starts fresh so its steps, runtime data, and Activity history belong only to our experiments with time.
Build the Lesson 18 test Pipeline
We will use a familiar Pipeline pattern to investigate time.
Create the new Lesson 18 Pipeline using the same basic experimental pattern we have used in earlier lessons. Add a Search Records step for the Tasks table, followed by an Update Record step inside the Loop created for the search results.
Step 1
Search Records
Search the Lesson 18 Tasks table. We will change the search criteria during the lesson depending on which date behavior we are investigating.
Step 2
Loop through the results
Search Records gives us a collection of Tasks. The Loop lets the Update Record step work with each returned Task individually.
Step 3
Update Pipeline Results
Update the current Task and use its Pipeline Results field as our laboratory output.
Pipeline Results is our test bench.
Throughout Lesson 18, most of the Jinja expressions we write will go into the Pipeline Results field mapping in the Update Record step. After running the Pipeline, return to the Tasks table and inspect Pipeline Results beside the Task's Due Date, Date Completed, Status, Project dates, and other fields involved in the experiment.
This gives us two forms of evidence. The Activity Log shows what the Pipeline received and executed at runtime, while the Tasks table preserves the Jinja-produced result beside the business data that produced it. We can compare the two instead of guessing what the expression did.
Expect this Pipeline to change during the lesson. We are not building the final automation yet. We will deliberately change Search Records criteria and replace the Jinja written to Pipeline Results as each experiment asks a new question about time.
Why fresh data? Some records in these files are intentionally unusual. Do not clean them up simply because they look wrong. Those edge cases give us evidence for what our date logic actually does when business data is incomplete, contradictory, or sitting directly on a time boundary.
Central idea
Time can change business state without changing the record.
Until now, most of our Pipelines have reacted to something that happened to a record. A field changed, a record was updated, or some other event gave the Pipeline a reason to run. Time-driven automation introduces a different kind of change.
Imagine a Task due today at 10:00 AM. At 9:55 AM it is still upcoming. At 10:05 AM it is overdue. The Task did not need to be edited for that business state to change. The clock moved, and the meaning of the existing data changed with it.
That is why a record-update trigger alone cannot represent every time-driven business process. Sometimes automation must wake up, examine records that have not changed, compare their stored dates with the current time, and decide what those dates mean now.
A new question
What time is it?
That sounds like a simple question until an app, a Pipeline, and a scheduler are involved.
During this lesson we will discover that Quickbase can represent the same business moment in different time contexts. Understanding which context we are looking at becomes essential before we compare dates, calculate durations, or schedule automation.
The three clocks
One business process can involve three different time contexts.
We are going to keep track of three "clocks" throughout this lesson. They are not three clocks literally ticking independently. They are three places where time is interpreted or represented during the life of our automation.
Clock 1 · The application
App timezone
This is the human-facing clock. It affects how Quickbase presents and interprets Date/Time values in the application. When someone enters a Due Date and sees a time on a Task, this is the context that makes that time meaningful to the user.
Think: "What time does the Quickbase user see?"
Clock 2 · The execution
Pipeline runtime UTC
When our Pipeline receives Date/Time values, Activity and runtime references can expose the underlying instant in UTC. This is the time context we will actually use while subtracting datetimes, measuring elapsed time, and comparing a Due Date with the moment a Pipeline run began.
Think: "What instant is the Pipeline calculating with?"
Clock 3 · The automation
Scheduler timezone
A scheduled Pipeline needs its own answer to "when should I run?" The scheduler's timezone determines when a configured schedule is due to start. Once that run begins, the Pipeline has its own runtime timestamp.
Think: "When should the Pipeline wake up and look?"
Keep these clocks separate.
The app timezone does not tell us when a scheduled Pipeline starts. The scheduler timezone does not tell us how a Date/Time is displayed on a Task form. And the UTC timestamp we encounter during execution may not look like the local time the user entered even though both represent the same instant.
We will prove these differences instead of simply memorizing them. Then we will use that model to calculate completion durations, detect overdue Tasks, compare Task deadlines with Project targets, and finally decide when a Pipeline should reevaluate time-sensitive business state.
1. Give time a business rule we can test
We now have three time contexts to keep straight: the time users see in the app, the UTC values a Pipeline works with at runtime, and the timezone that determines when a scheduled Pipeline starts. Before we can investigate how those pieces behave, however, we need a business rule with an answer we already know.
Our Lesson 18 rule: a Task has a three-hour completion requirement.
For a completed Task, we will compare its Due Date with its Date Completed. If the Task was completed no more than three hours after its Due Date, it is within the requirement. Anything beyond three hours is outside the requirement.
This rule gives our date experiments something concrete to prove. We are not subtracting timestamps merely to learn Jinja syntax. We need the Pipeline to turn two Date/Time values into a reliable business decision.
2:59
Must pass
One minute inside the boundary
3:00
Must pass
Exact boundary
3:01
Must fail
One minute outside the boundary
The Lesson 18 Tasks were deliberately built around this boundary. Some finish well inside three hours, some well outside it, and three records sit at 2:59, 3:00, and 3:01. We also included midnight crossings, future Tasks, missing completion dates, and contradictory business data. The goal is not pretty sample data. It is data capable of making a wrong time model fail visibly.
Do not clean away the ugly record.
Record #42 intentionally has Status = Complete while Date Completed is blank. It looks wrong because it is wrong. Later, that contradiction will help us discover why correct date arithmetic is not enough to make a correct business decision.
Where this is going
We will begin with the easiest case: a Task that already has both timestamps. First we will discover how Pipeline Date/Time values behave and calculate the elapsed time between Due Date and Date Completed. Once that model works, we will remove Date Completed from the equation and ask a harder question: how can a Pipeline measure a Task against the current time?
From there, we can move beyond a single Task's deadline, compare it with its parent Project's Target Date, and finally ask when a scheduled Pipeline should wake up and reevaluate all of this changing business state.
2. Timezone investigation: know the app's clock before testing time
Before calculating a single duration, we needed to verify the first of our three clocks: the application timezone. A Due Date that displays as 3:00 PM is only useful test evidence if we understand which timezone Quickbase is using to interpret and display that 3:00 PM.
Our Lesson 18 app was not initially using Central Time.
When we inspected the Automation app's settings, its timezone was following the billing account timezone, which was set to Pacific Time. That explained why the Date/Time values displayed in the app did not match the Central Time values we intended for our Lesson 18 test records.
Nothing was wrong with datetime arithmetic yet. Our test environment was using a different local-time context than we expected.
Check the application setting
App Settings → App properties
Open the application's settings and inspect its properties for the application timezone. This is where you can determine whether the app is following the billing account's timezone or using an override for this particular application.
For our Automation app, the inherited setting led us back to the billing account's Pacific timezone. Because our Lesson 18 data was designed around Central Time, we changed the application's timezone override to Central Time.
Before continuing
Make your test data agree with your app timezone
Verify the timezone you intend to use before entering or correcting the Lesson 18 Date/Time values. If you change the app timezone after Date/Time values already exist, inspect those records again instead of assuming the displayed clock times will remain unchanged.
After changing our app from Pacific to Central Time, the same stored instants displayed two hours later. We then corrected the Lesson 18 Tasks under the Central Time setting so the visible Due Date and Date Completed values matched the test cases we intended to prove.
Why did changing the timezone change what we saw?
A Date/Time represents a moment, while the application timezone controls how that moment is presented in local time. Changing the app's timezone did not give us a new moment in time. It changed the local clock representation of the existing instant.
This is our first reason to keep display time and runtime time conceptually separate. The user may see a familiar Central Time value in the Tasks table while Pipeline Activity exposes that same moment as UTC.
Compare the app with Pipeline runtime
Once the app and our Lesson 18 records were corrected to Central Time, we ran the Pipeline and inspected the Date/Time values it received. These examples connect the local values visible in Quickbase with the UTC instants exposed during Pipeline execution.
Sep. 5, 6:00 AM Central
2026-09-05 11:00:00+00:00September was using daylight time: Central was UTC−5.
Nov. 22, 4:00 PM Central
2026-11-22 22:00:00+00:00November was using standard time: Central was UTC−6.
Dec. 1, 9:00 AM Central
2026-12-01 15:00:00+00:00December remained on standard time: Central was UTC−6.
Do not solve this by memorizing UTC offsets.
Notice that Central Time did not even have one fixed UTC offset across our lesson data. September produced a five-hour difference while November and December produced six. Daylight-saving time changed the offset.
The useful lesson is therefore not "add five hours" or "add six hours." It is to understand which time context you are looking at and let timezone-aware Date/Time values represent the actual instant.
Clock 1 established
We now know what the application clock is doing and have corrected our test environment. Next we can move to Clock 2: the Date/Time objects the Pipeline actually receives, and whether Jinja can perform arithmetic with them directly.
3. A useful failure: Activity output is not the Jinja object API
Activity expanded a Date/Time with properties such as time and iso. We predicted that .time might therefore be a numeric value available to Jinja.
If that were true, we could subtract the two values, calculate an elapsed duration, and then test our three-hour business rule.
Put this Jinja in Pipeline Results
In the Lesson 18 Pipeline, open the Update Record step and place the following Jinja into the Pipeline Results field mapping.
Then run the Pipeline and inspect the Task record. Pipeline Results is our visible test output, while the Activity Log tells us what happened during execution.
{# Try to subtract the two Date/Time values by using
the .time value we saw in Activity output. #}
{% set elapsed_seconds = aa.date_completed.time - aa.due_date.time %}
{# If elapsed_seconds is numeric, convert seconds into minutes
so the duration is easier to read. #}
{% set elapsed_minutes = elapsed_seconds / 60 %}
{# Write both calculated values into Pipeline Results
so we can inspect what the Pipeline produced. #}
Elapsed seconds: {{ elapsed_seconds }}
Elapsed minutes: {{ elapsed_minutes }}
{# Three hours equals 10,800 seconds.
Use that boundary to classify the Task. #}
{% if elapsed_seconds <= 10800 %}
WITHIN 3-HOUR REQUIREMENT
{% else %}
OVER 3-HOUR REQUIREMENT
{% endif %}What this code is trying to do
1. Subtract the timestamps. aa.date_completed.time - aa.due_date.time assumes the.time values exposed in Activity are numeric values that Jinja can subtract.
2. Convert seconds to minutes. If the subtraction returned a number of seconds, dividing by 60 would give us elapsed minutes.
3. Print the result. The two output lines would make the calculated values visible in the Task's Pipeline Results field.
4. Apply the business rule. Three hours equals 10800 seconds, so the final if statement would classify the Task as within or over the three-hour requirement.
Observed error
unsupported operand type(s) for -: &aposbuiltin_function_or_method&apos and 'builtin_function_or_method&aposThe failure tells us something important: Activity serialization showed labels named time and iso, but that did not mean those labels were numeric Jinja properties. Jinja interpreted .time as a callable method instead of the number we expected.
This is why we use Pipeline Results and Activity together. The field shows us what our expression produced—or failed to produce—while Activity gives us the runtime evidence needed to correct our model instead of guessing.
Evidence lesson
Activity serialization tells us how Quickbase describes runtime data. It does not automatically define the Jinja object API. We must test what Jinja can actually access and operate on.
4. The simpler model worked: subtract the datetimes
Instead of extracting seconds first, we asked Jinja to subtract one complete Date/Time value from another.
{# Show the two Date/Time values exactly as the Pipeline sees them. #}
Due: {{ aa.due_date }}
Completed: {{ aa.date_completed }}
{# Subtract the Due Date directly from Date Completed.
This tests whether Jinja can perform datetime arithmetic
without trying to extract a separate numeric .time property. #}
Difference: {{ aa.date_completed - aa.due_date }}Record #37
2:59:00
Record #38
3:00:00
Record #36
3:01:00
Crossing midnight required no special case. Full Date/Time subtraction handled #35 and #43 correctly because the date is part of the value.
5. Separate calculation from classification
The subtraction produced a duration. Calling .total_seconds() gave us a stable number for the business rule. Three hours equals 10,800 seconds.
{# Subtract Due Date from Date Completed.
The result is a duration, not a plain number. #}
{% set elapsed = aa.date_completed - aa.due_date %}
{# Convert that duration into total seconds so we can
compare it against a fixed business threshold. #}
{% set seconds = elapsed.total_seconds() %}
{# Three hours = 10,800 seconds.
The exact 3:00 boundary still counts as within the requirement. #}
{% if seconds <= 10800 %}
WITHIN 3-HOUR REQUIREMENT
{% else %}
OVER 3-HOUR REQUIREMENT
{% endif %}| Record | Duration | Seconds | Result |
|---|---|---|---|
| #31 | 3:30:00 | 12600 | OVER |
| #32 | 2:00:00 | 7200 | WITHIN |
| #33 | 0:00:00 | 0 | WITHIN |
| #34 | 0:15:00 | 900 | WITHIN |
| #35 | 2:00:00 | 7200 | WITHIN |
| #36 | 3:01:00 | 10860 | OVER |
| #37 | 2:59:00 | 10740 | WITHIN |
| #38 | 3:00:00 | 10800 | WITHIN |
| #39 | 0:45:00 | 2700 | WITHIN |
| #40 | 5:00:00 | 18000 | OVER |
| #41 | 4:00:00 | 14400 | OVER |
| #43 | 3:01:00 | 10860 | OVER |
Boundary proven: 2:59 passed, 3:00 passed, and 3:01 failed. The code matched the intended <= 10800 rule exactly.
6. Replace completion time with the moving clock
Completed records have two fixed timestamps. Incomplete records do not. To ask what state an unfinished Task is in now, we used the Pipeline run timestamp, runtime.triggered_at.
{# runtime.triggered_at gives us the UTC timestamp
for when this Pipeline run began. This becomes our "current time"
for every record evaluated during this run. #}
Run started: {{ runtime.triggered_at }}
{# Show the Task's stored Due Date for comparison. #}
Due: {{ aa.due_date }}
{# Instead of comparing two dates stored on the record,
subtract the Due Date from the Pipeline's run time.
Positive duration = the Due Date is in the past.
Negative duration = the Due Date is still in the future. #}
Difference: {{ runtime.triggered_at - aa.due_date }}Observed at run start: 2026-09-18 17:14:49.379765+00:00
- #42: positive difference → Due Date was already in the past.
- #44: negative difference → Due Date was still in the future.
- #45: negative difference → Due Date was still in the future.
Sign now has meaning: negative means the due instant is ahead of the run; positive means the run has moved past it.
{# Compare the Pipeline's run time with the Task's Due Date.
The result tells us where the Task sits relative to "now." #}
{% set elapsed = runtime.triggered_at - aa.due_date %}
{# Convert the duration into seconds so its sign and size
can be tested against our three-hour business window. #}
{% set seconds = elapsed.total_seconds() %}
{# A negative result means the Due Date has not arrived yet.
The Task is still upcoming. #}
{% if seconds < 0 %}
UPCOMING
{# Zero through 10,800 seconds means the Due Date has passed,
but by no more than three hours. #}
{% elif seconds <= 10800 %}
WITHIN 3-HOUR WINDOW
{# Anything greater than 10,800 seconds means more than
three hours have passed since the Task was due. #}
{% else %}
OVER 3-HOUR WINDOW
{% endif %}7. Correct arithmetic is not enough
Record #42 exposed the difference between mathematical state and business state. Its Date Completed was blank, but Status said Complete. If we classified only by time, we would call it overdue and hide a data-quality problem.
{# Compare the Pipeline's run time with the Due Date
and convert the resulting duration into seconds. #}
{% set elapsed = runtime.triggered_at - aa.due_date %}
{% set seconds = elapsed.total_seconds() %}
{# Check the business data BEFORE classifying the Task by time.
A Complete Task with no Date Completed contradicts our expected data,
so we identify it as an exception instead of calling it overdue. #}
{% if aa.status == 'Complete' %}
DATA EXCEPTION — COMPLETE WITHOUT COMPLETION DATE
{# Only records that pass the business-data check continue
into our normal time-based classification. #}
{% elif seconds < 0 %}
UPCOMING
{# The Due Date has passed, but by no more than three hours. #}
{% elif seconds <= 10800 %}
WITHIN 3-HOUR WINDOW
{# More than three hours have passed since the Due Date. #}
{% else %}
OVERDUE
{% endif %}#42
DATA EXCEPTION — COMPLETE WITHOUT COMPLETION DATE
#44
UPCOMING
#45
UPCOMING
Business rules need precedence. Sometimes the most important answer is not the time classification—it is that the record contradicts itself.
8. Time can cross a relationship boundary
The Tasks table also exposed the parent Project Target Date through the relationship. That let us compare two different business clocks: when the Task is due and when the Project is targeted.
{# Show the Task and the two dates we are about to compare.
The Project Target Date reaches the Task through the table relationship. #}
Task: {{ aa.task_name }}
Task Due: {{ aa.due_date }}
Project Target: {{ aa.project_target_date }}
{# Subtract the Task's Due Date from the Project Target Date.
This gives us the amount of time separating the two deadlines. #}
{% set project_gap = aa.project_target_date - aa.due_date %}
{# Write the calculated gap into Pipeline Results so we can
inspect both the duration and the classification that follows. #}
Task-to-Project Gap: {{ project_gap }}
{# If the Task is due later than the Project Target Date,
the Task's own schedule extends beyond its parent Project's target. #}
{% if aa.due_date > aa.project_target_date %}
TASK DUE AFTER PROJECT TARGET
{# Equal Date/Time values mean the Task is due exactly
at the Project's Target Date. #}
{% elif aa.due_date == aa.project_target_date %}
TASK DUE AT PROJECT TARGET
{# Otherwise, the Task is scheduled before the Project Target Date. #}
{% else %}
TASK DUE BEFORE PROJECT TARGET
{% endif %}#44
Task due before Project target.
#45
Task due after Project target.
#42
Task due before Project target.
This revealed a useful conflict: #45 was still UPCOMING relative to the current run, yet its Task Due Date was already later than the parent Project Target Date. “Not overdue yet” does not mean “schedule is healthy.”
9. Combine the rules—and make their order intentional
The final expression did more than calculate time. It encoded which business concern should win when several facts are simultaneously true.
{# Establish the Task's position relative to the current Pipeline run
and convert that duration into seconds for our time-based rules. #}
{% set elapsed = runtime.triggered_at - aa.due_date %}
{% set seconds = elapsed.total_seconds() %}
{# Rule 1: Check data integrity first.
A Complete Task without Date Completed is contradictory business data,
so do not allow the time calculation to misclassify it as overdue. #}
{% if aa.status == 'Complete' %}
DATA EXCEPTION — COMPLETE WITHOUT COMPLETION DATE
{# Rule 2: Check the Task against its parent Project.
Even an upcoming Task can already represent a schedule conflict
if its Due Date falls after the Project's Target Date. #}
{% elif aa.due_date > aa.project_target_date %}
PROJECT SCHEDULE CONFLICT — TASK DUE AFTER PROJECT TARGET
{# Rule 3: If no higher-priority problem exists, classify by current time.
A negative duration means the Task's Due Date is still in the future. #}
{% elif seconds < 0 %}
UPCOMING
{# The Due Date has arrived, but no more than three hours have passed. #}
{% elif seconds <= 10800 %}
WITHIN 3-HOUR WINDOW
{# Anything remaining is more than three hours past its Due Date. #}
{% else %}
OVERDUE
{% endif %}Observed precedence
- Contradictory completion data wins first.
- Project schedule conflict wins before ordinary upcoming/overdue state.
- Then the moving clock classifies the remaining records.
The order of conditions is part of the business policy.
10. Scheduling: the clock has to make us look again
Our classifier can determine state at runtime, but an incomplete Task does not need to mutate for its state to change. A schedule gives the Pipeline another opportunity to evaluate the current state.
Schedule
When do we look?
Record time
What state do we find?
Pipeline
What happens next?
Quickbase scheduling supports normal hourly/daily/weekly/monthly/yearly choices plus an advanced five-field CRON expression. Scheduling cannot run more often than once per hour.
Every hour
0 * * * *12:51 AM on the last day of each month
51 0 L * *We kept CRON intentionally brief. The architectural lesson matters more than memorizing scheduler syntax.
The model we leave Lesson 18 with
1 · Calculate
Subtract complete Date/Time values. Convert the duration to seconds only when the rule needs a numeric threshold.
2 · Classify
Turn arithmetic into business meaning: upcoming, within window, overdue, conflict, or data exception.
3 · Reevaluate
When state can change because time moved, schedule another evaluation rather than waiting for a record mutation.
The schedule determines WHEN WE LOOK. The record's time determines WHAT WE FIND. The Pipeline determines WHAT HAPPENS NEXT.
Scope boundary
This lesson stops at time manipulation and scheduling. A later lab can take these classifications into downstream delivery, API calls, report generation, email, and more advanced execution control. Those are valuable—but they are separate automation concerns and should not blur what Lesson 18 actually proved.
Lesson 18 knowledge check
Decide True or False before opening each explanation.
1.A Task must be edited before its time-based business state can change.
2.If Activity shows a property named time, Jinja can safely treat .time as a numeric timestamp.
3.Subtracting two Quickbase Date/Time values can produce a duration that crosses midnight correctly.
4.Exactly three hours should fail a rule written as seconds <= 10800.
5.A mathematically overdue Task should always be labeled OVERDUE before checking other business data.
6.A Task can be upcoming relative to now and still conflict with its Project Target Date.
7.Scheduler timezone and runtime.triggered_at describe the same thing.
Lesson 18 Evidence Ledger
What we actually proved
This lesson was built from controlled Pipeline experiments. These are observations from our lab—not assumptions about how time ought to work.
Quickbase Date/Time values can be subtracted directly in Pipeline Jinja.
The resulting duration supports total_seconds() for numeric comparisons.
A 3:00:00 duration passed our <= 10,800-second rule; 3:01:00 failed it.
Datetime subtraction worked across midnight without special-case logic.
runtime.triggered_at gave the Pipeline a consistent UTC run-start timestamp.
Negative runtime-to-due durations identified future Due Dates; positive durations identified past Due Dates.
Application timezone changed how stored instants were presented without changing the underlying instant.
A related Project Target Date could participate directly in Task-level Jinja date comparisons.
Correct date arithmetic did not resolve contradictory business data; business rules still had to decide what took priority.
The order of Jinja if/elif conditions determined which business classification won when multiple conditions were true.
The larger lesson
A record does not have to change for its business meaning to change. The clock can move a Task from upcoming, to within its response window, to overdue while every field on the record remains untouched. Scheduling gives the Pipeline a way to wake up, look again, and make that changing state actionable.
Continue the Lab
Ready for Lesson 19?
Lesson 18 showed how time can become business state inside a Pipeline. Continue to Lesson 19, or return to the Lessons page to review the complete Automation Developer Lab.