Between Times Check Examples
Three real-world scenarios that show how the Between Times check is typically used in production: keeping order dates inside a reporting quarter, validating shift timestamps with a filter, and catching implausible activity dates. The first two run at 100% coverage and report Record Anomalies; the third lowers coverage and reports a Shape Anomaly instead.
The situation: A quarterly reporting table is rebuilt from the orders feed. Every row loaded into it must carry an o_orderdate inside the 2026 first quarter, from 2026-01-01 00:00 UTC through 2026-03-31 23:59:59 UTC. Anything outside that window means the extract pulled the wrong slice.
Check configuration
| Field | Value |
|---|---|
| Rule | Between Times |
| Field | o_orderdate |
| Filter | (none) |
| Custom Anomaly Description | Off |
| Min | 2026-01-01 00:00:00 UTC |
| Max | 2026-03-31 23:59:59 UTC |
| Coverage | 100% |
| Owner | (check creator) |
| Anomaly Assignee | (Reporting Data team) |
| Description | Order dates must fall inside the 2026 first quarter. |
| Tags | reporting, period |
| Additional Metadata | jira: DATA-6401 |
| Status | Active |
Payload
{
"description": "Order dates must fall inside the 2026 first quarter.",
"rule": "betweenTimes",
"fields": ["o_orderdate"],
"container_id": 318,
"coverage": 1,
"filter": null,
"properties": {
"min_time": "2026-01-01T00:00:00Z",
"max_time": "2026-03-31T23:59:59Z"
},
"tags": ["reporting", "period"],
"additional_metadata": {"jira": "DATA-6401"},
"anomaly_message_field": null,
"template_id": null,
"status": "Active",
"owner_id": 7,
"default_anomaly_assignee_id": 12
}
Sample Data
| o_orderkey | o_orderdate | o_orderstatus |
|---|---|---|
| 5001 | 2026-01-01 00:00:00 | O |
| 5002 | 2026-02-17 11:32:00 | F |
| 5003 | 2026-04-02 08:10:00 | O |
| 5004 | 2026-03-31 23:59:59 | F |
What gets flagged
Order 5003 is dated in April, outside the quarter. Orders 5001 and 5004 sit exactly on the two boundaries and pass, because both edges are inclusive. Coverage is 100%, so the failing row is reported as a Record Anomaly.
Record Anomaly
The field 'o_orderdate' has value 2026-04-02 08:10:00, which is not between 2026-01-01T00:00:00Z and 2026-03-31T23:59:59Z
Flowchart
graph TD
A["No filter, evaluate all rows"] --> B["Interpret o_orderdate as timestamp"]
B --> C{"Is o_orderdate >= Min<br/>AND <= Max?"}
C -->|Yes| D["Row passes"]
C -->|No| E["Flag row.<br/>Record Anomaly per failing row."]
Equivalent SQL
The situation: Badge events for the night shift must be stamped inside the shift window, from 2026-05-10 22:00 UTC through 2026-05-11 06:00 UTC. Day-shift events live in the same table and are out of scope for this check.
Check configuration
| Field | Value |
|---|---|
| Rule | Between Times |
| Field | event_at |
| Filter | shift = 'night' |
| Custom Anomaly Description | Off |
| Min | 2026-05-10 22:00:00 UTC |
| Max | 2026-05-11 06:00:00 UTC |
| Coverage | 100% |
| Owner | (check creator) |
| Anomaly Assignee | (Workforce Systems) |
| Description | Night-shift badge events must fall inside the shift window. |
| Tags | workforce, period |
| Additional Metadata | jira: DATA-6455 |
| Status | Active |
Payload
{
"description": "Night-shift badge events must fall inside the shift window.",
"rule": "betweenTimes",
"fields": ["event_at"],
"container_id": 826,
"coverage": 1,
"filter": "shift = 'night'",
"properties": {
"min_time": "2026-05-10T22:00:00Z",
"max_time": "2026-05-11T06:00:00Z"
},
"tags": ["workforce", "period"],
"additional_metadata": {"jira": "DATA-6455"},
"anomaly_message_field": null,
"template_id": null,
"status": "Active",
"owner_id": 7,
"default_anomaly_assignee_id": 33
}
Sample Data (filtered to shift = 'night')
| event_id | shift | event_at |
|---|---|---|
| E-701 | night | 2026-05-10 22:04:00 |
| E-702 | night | 2026-05-11 07:12:00 |
| E-703 | night | 2026-05-11 05:58:00 |
Why the filter matters
The filter runs before the comparison, so day-shift events are never tested against the night window. Only night-shift rows are evaluated.
What gets flagged
E-702 was stamped at 07:12, after the shift ended, so it is the only row reported. Coverage is 100%, so the failure is reported as a Record Anomaly, and the message ends with the filter that scoped the evaluation.
Record Anomaly
The field 'event_at' has value 2026-05-11 07:12:00, which is not between 2026-05-10T22:00:00Z and 2026-05-11T06:00:00Z [filter: shift = 'night']
Flowchart
graph TD
A["Apply filter: shift = 'night'"] --> B["Interpret event_at as timestamp"]
B --> C{"Is event_at >= Min<br/>AND <= Max?"}
C -->|Yes| D["Row passes"]
C -->|No| E["Flag row.<br/>Anomaly message ends with<br/>[filter: shift = 'night']"]
Equivalent SQL
The situation: An activity log should only hold events from the period the platform has existed, between 2015-01-01 00:00 UTC and 2026-12-31 23:59:59 UTC. A small fraction of rows carries dates from a broken importer and is being cleaned up, so the check tolerates up to 0.5% failures. Rows whose date failed to parse upstream are NULL.
Check configuration
| Field | Value |
|---|---|
| Rule | Between Times |
| Field | activity_at |
| Filter | (none) |
| Custom Anomaly Description | Off |
| Min | 2015-01-01 00:00:00 UTC |
| Max | 2026-12-31 23:59:59 UTC |
| Coverage | 99.5% |
| Owner | (check creator) |
| Anomaly Assignee | (Platform Data team) |
| Description | Activity dates must fall inside the platform's lifetime. |
| Tags | plausibility, activity |
| Additional Metadata | jira: DATA-6502 |
| Status | Active |
Payload
{
"description": "Activity dates must fall inside the platform's lifetime.",
"rule": "betweenTimes",
"fields": ["activity_at"],
"container_id": 904,
"coverage": 0.995,
"filter": null,
"properties": {
"min_time": "2015-01-01T00:00:00Z",
"max_time": "2026-12-31T23:59:59Z"
},
"tags": ["plausibility", "activity"],
"additional_metadata": {"jira": "DATA-6502"},
"anomaly_message_field": null,
"template_id": null,
"status": "Active",
"owner_id": 7,
"default_anomaly_assignee_id": 48
}
Sample Data
| activity_id | activity_at | source |
|---|---|---|
| A-9001 | 2024-08-19 14:22:00 | web |
| A-9002 | 1970-01-01 00:00:00 | importer |
| A-9003 | 2099-05-01 00:00:00 | importer |
| A-9004 | (null) | importer |
What gets flagged
Activities A-9002 and A-9003 carry an epoch date and a far-future date, both from the broken importer. A-9004 is NULL, so it passes without firing an anomaly but still counts in the scanned total. Only 50% of the rows pass, which is below the 99.5% coverage threshold, so the check reports a single Shape Anomaly for the dataset with a sample of the offending rows. Coverage below 100% does not produce Record Anomalies.
Shape Anomaly
For the field 'activity_at', 50.000% of 4 records (2) are not between 2015-01-01T00:00:00Z and 2026-12-31T23:59:59Z
Flowchart
graph TD
A["No filter, evaluate all rows"] --> B["Interpret activity_at as timestamp"]
B --> C{"Is value NULL?"}
C -->|Yes| D["Row passes"]
C -->|No| E{"Is activity_at >= Min<br/>AND <= Max?"}
E -->|Yes| D
E -->|No| F["Flag row.<br/>Passing rate falls below the 99.5%<br/>coverage, so one Shape Anomaly is reported."]
Equivalent SQL
See Also
-
How It Works
The complete reference: definition, field scope, properties, inclusive boundaries, NULL handling, filter behavior, and coverage.
-
Anomaly Reporting
The anomaly messages the check produces, what the numbers mean, Source Records highlighting, and Custom Anomaly Description.
-
Best Practices
Guidelines for choosing the window, handling time zones, pairing rules, and keeping the signal clean.
-
Permissions
The team permission each action needs: view, create, edit, archive, restore, and delete.