dhruv-techdev opened a new issue, #75528:
URL: https://github.com/apache/airflow/issues/75528
### Under which category would you file this issue?
Providers
### Apache Airflow version
main (commit 57a4751c96, airflow-core 3.4.0)
### What happened and how to reproduce it?
**Issue Description**
When `target_lower` / `target_upper` are `datetime.time` values and the
window spans midnight (for example `target_lower=time(22, 0)`,
`target_upper=time(2, 0)`), `BranchDateTimeOperator` follows
`follow_task_ids_if_false` for any time between midnight and `target_upper`,
even though that time is inside the window.
`target_times_as_dates` combines both times with the current date, then only
moves `upper` forward one day when `upper < lower`:
```python
if upper < lower:
upper += datetime.timedelta(days=1)
```
At 01:00 on Jan 2 this builds the window Jan 2 22:00 → Jan 3 02:00
(tonight's window). The window that contains 01:00 is Jan 1 22:00 → Jan 2 02:00
(last night's), so the `lower > now` check sends the run to the false branch.
**Steps to reproduce:**
Run this test against `main` (no database needed):
```python
import datetime
import pendulum
import pytest
from airflow.providers.standard.operators.datetime import
BranchDateTimeOperator
from airflow.sdk import DAG
def make_operator():
with DAG("overnight_window_repro", schedule=None,
start_date=pendulum.datetime(2026, 1, 1, tz="UTC")):
return BranchDateTimeOperator(
task_id="branch",
follow_task_ids_if_true="in_window",
follow_task_ids_if_false="outside_window",
target_lower=datetime.time(22, 0),
target_upper=datetime.time(2, 0),
use_task_logical_date=True,
)
@pytest.mark.parametrize(
("hour", "expected"),
[(23, "in_window"), (1, "in_window"), (12, "outside_window")],
)
def test_overnight_window(hour, expected):
now = pendulum.datetime(2026, 1, 2, hour, 0, tz="UTC")
assert make_operator().choose_branch({"logical_date": now}) == expected
```
Result:
```
test_overnight_window[23-in_window] PASSED
test_overnight_window[1-in_window] FAILED
test_overnight_window[12-outside_window] PASSED
E AssertionError: -'outside_window' +'in_window'
```
`use_task_logical_date=True` only fixes "now" for the test. The default mode
(`use_task_logical_date=False`, real clock) goes through the same
`target_times_as_dates` code.
### What you think should happen instead?
A time between midnight and `target_upper` in an overnight window should
follow `follow_task_ids_if_true`. The operator docs say that when
`target_upper` is earlier than `target_lower`, "a day will be added to
`target_upper`. This is done to allow for time periods that span over two
dates." Today only the part before midnight works.
The documented example (15:00 → 00:00) doesn't show the problem because its
window ends exactly at midnight, so it has no after-midnight part.
This is separate from #74838, which changes which date the times are
combined with (the Dag-timezone date instead of the UTC date). It doesn't touch
the `upper < lower` logic, so the bug remains with that change applied.
### Operating System
macOS 27.0.1
### Deployment
Virtualenv installation
### Apache Airflow Provider(s)
standard
### Versions of Apache Airflow Providers
_No response_
### Official Helm Chart version
Not Applicable
### Kubernetes Version
N/A
### Helm Chart configuration
N/A
### Docker Image customizations
N/A
### Anything else?
It happens every time, for every run that falls between midnight and
`target_upper` in an overnight window. There's no error in the logs: the
operator just follows the wrong branch, so downstream tasks are silently
skipped or run.
### Are you willing to submit PR?
- [x] Yes I am willing to submit a PR!
### Code of Conduct
- [x] I agree to follow this project's [Code of
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]