CaptainAni187 opened a new pull request, #72703:
URL: https://github.com/apache/airflow/pull/72703

   Closes: #72694
   
   `td_format` renders a negative duration as a large positive one:
   
   ```python
   td_format(timedelta(seconds=-3752))   # '29d:22h:57M:28s'
   td_format(timedelta(days=-5))         # '25d'
   td_format(-3752)                      # '<1s'
   ```
   
   The last two lines are the same duration expressed two ways and they 
disagree.
   
   ### Cause
   
   The day-to-month conversion uses `divmod`, which floors:
   
   ```python
   months, delta.days = divmod(delta.days, 30)
   ```
   
   so a `relativedelta` of `days=-1` becomes `months=-1, days=+29`. 
`_format_part` skips any component below 1, which drops the `-1 month` that 
would have cancelled the `+29 days` and leaves the days behind.
   
   The numeric branch differs because `relativedelta(seconds=-3752)` keeps a 
single negative `seconds` field instead of borrowing a day, so every component 
is dropped and the empty result falls through to `<1s`.
   
   ### Change
   
   Format the magnitude, then re-apply the sign. This keeps the existing output 
for non-negative durations untouched and makes the two input types agree:
   
   ```python
   td_format(timedelta(seconds=-3752))   # '-1h:2M:32s'
   td_format(timedelta(days=-5))         # '-5d'
   td_format(-3752)                      # '-1h:2M:32s'
   ```
   
   A magnitude below one second still reads `<1s` regardless of sign, since 
prefixing a sign onto `<1s` would not tell the reader anything useful.
   
   ### Tests
   
   Adds `test_td_format_negative` alongside the existing `test_td_format`, 
covering both input types, the sub-second case, and the agreement between the 
two branches. It fails on `main` with `'29d:22h:57M:28s' != '-1h:2M:32s'`.
   
   I also checked the sign invariant `td_format(-x) == "-" + td_format(x)` over 
20,000 randomly generated durations for both input types, along with cross-type 
agreement — no violations. That sweep is not included in the test file, since 
the explicit cases cover the behaviour and are easier to read.
   
   `ruff check` and `ruff format` are clean at the pinned 0.16.4, and the 
`shared/timezones` suite passes (31 passed).
   


-- 
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]

Reply via email to