Exemplo
python-dateutil 2.9.0.post0: Perform calendar unit arithmetic with dateutil.relativedelta.relativedelta including month-end clipping, nth-weekday offsets, and date difference decomposition in python-dateutil 2.9.0.post0
Amostra verificada para pypi python-dateutil 2.9.0.post0: Perform calendar unit arithmetic with dateutil.relativedelta.relativedelta including month-end…
sha256:e571410004610c074e21149958996cbb121933e9ce9355cb94026e7fd944e097
Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu.
Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas.
MIT-0
Evidência de execução
O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.
- Base da evidência
- Contrato assinado aprovado
- Recibos de verificação
- 3
- Chaves de assinatura que o compilaram
- 3
Ambiente declarado
python linux x64 python python pip
Ambientes das execuções de verificação
| Ambiente | Contrato | Etapas | Execução |
|---|---|---|---|
| python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-17 |
| python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-18 |
| python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104… |
2026-09-08 |
Caso
HOW- Objetivo
- Perform calendar unit arithmetic with dateutil.relativedelta.relativedelta including month-end clipping, nth-weekday offsets, and date difference decomposition in python-dateutil 2.9.0.post0
- Pacotes
- Símbolos
-
- dateutil.relativedelta.relativedelta
- Ambiente
- python
- Criado
- 2026-08-17T14:50:45Z
Contrato
- Adding calendar months or years with relativedelta clips overflow days to the last valid day of the target month, ensuring dates like January 31 advance to February 28 or 29 without raising an error
- relativedelta distinguishes relative offsets using plural kwargs from absolute field replacements using singular kwargs and allows combining both in a single operation
- Unindexed and nth-instance weekday specifications navigate forward or backward to target weekdays relative to a reference date
- Computing relativedelta between two datetimes decomposes the exact elapsed time into normalized calendar units that reconstruct the original date when added
Arquivos
- NOTES.md
- csx.json
- requirements.txt
- test/contract.py
Código-fonte
# python-dateutil Relativedelta Calendar Arithmetic and Decomposition
## Initial Network Search & Prior Samples
Before authoring this specification, network search was invoked for `pkg:pypi/python-dateutil`.
The search found existing published samples covering timezone parsing:
- **Sample ID**: `sha256:1d61102c9dc6e665004c4e0e9c48b2388643d4b1c449c70394827ad9a6dab848`
- **Goal**: *"Configure timezone strings with dateutil.tz.tzstr and posix_offset to handle POSIX offset sign inversion versus ISO-8601 conventions"*
- **Sample ID**: `sha256:c869de53f102a4d565bb2dc268b5131d576360610b8edd0bf6604b666bd8bcab`
- **Goal**: *"Resolve dateutil.tz.gettz('') to the local system timezone instead of returning None (fixed in 2.8.2)"*
This sample focuses on `dateutil.relativedelta.relativedelta`, verifying calendar unit arithmetic, month-end clipping, nth-instance weekday offsets, and bidirectional date interval decomposition.
---
## Target Release & Dependencies
- **Package**: `python-dateutil==2.9.0.post0`
- **Dependency**: `six==1.17.0`
---
## Observed Behaviour & Semantics
### 1. Calendar Month Arithmetic and Month-End Boundary Clamping
Standard library `datetime.timedelta` operates strictly on absolute intervals (days, seconds, microseconds) and cannot represent calendar concepts like months or years where duration varies.
`dateutil.relativedelta.relativedelta` introduces calendar-aware additions:
- Adding months to a date at month end clamps days that would exceed the destination month's length to the last valid day of that month. For example, `datetime(2023, 1, 31) + relativedelta(months=+1)` evaluates to `datetime(2023, 2, 28)`.
- In a leap year, `datetime(2024, 1, 31) + relativedelta(months=+1)` correctly preserves the leap day, yielding `datetime(2024, 2, 29)`.
- Adding one year to leap day (`datetime(2024, 2, 29) + relativedelta(years=+1)`) produces `datetime(2025, 2, 28)`.
### 2. Relative Offsets versus Absolute Field Replacements
`relativedelta` clearly distinguishes between relative offsets and absolute replacements:
- **Plural arguments** (`years`, `months`, `weeks`, `days`, `hours`, `minutes`, `seconds`, `microseconds`) add to or subtract from existing fields.
- **Singular arguments** (`year`, `month`, `day`, `hour`, `minute`, `second`, `microsecond`) replace the field on the target date.
- Both may be combined in a single `relativedelta` object, allowing simultaneous month increment and day pinning (e.g., `relativedelta(months=+1, day=1)`).
### 3. Weekday Relative Navigation
`relativedelta` supports weekday instances (`MO`, `TU`, `WE`, `TH`, `FR`, `SA`, `SU`):
- Unindexed weekday (e.g., `weekday=FR`) or `FR(+1)` moves to the next occurrence of that weekday, or keeps the current date if the date is already a Friday.
- Multipliers specify nth occurrences: `weekday=FR(+2)` targets the second Friday on or after the date, while `weekday=FR(-1)` targets the preceding Friday (or current date if already Friday) and `weekday=FR(-2)` targets the second preceding Friday.
- Combining weekday calculation with month boundary pinning enables expressions like `datetime(2023, 1, 1) + relativedelta(weekday=MO(+1))` to compute the first Monday of January, and `datetime(2023, 1, 31) + relativedelta(weekday=FR(-1))` to compute the last Friday of January.
### 4. Date Difference Decomposition and Reconstruction
Passing two `datetime` objects to `relativedelta(dt1, dt2)` decomposes the difference into calendar units:
- Normalized attributes `years`, `months`, `days`, `hours`, `minutes`, `seconds`, `microseconds` reflect the breakdown of elapsed time between `dt2` and `dt1`.
- Adding the decomposed `relativedelta` back to `dt2` reconstructs `dt1` precisely (`dt2 + rd == dt1`).
- Reversing the order (`relativedelta(dt2, dt1)`) yields identical magnitudes with negated signs, and adding this reverse delta to `dt1` reconstructs `dt2`.
{"case":{"caseId":"case:sha256:331656046cd873046ede0fdb30b9be45e6e03d33cf79d16d2dfde0bfb2710f44","contract":["Adding calendar months or years with relativedelta clips overflow days to the last valid day of the target month, ensuring dates like January 31 advance to February 28 or 29 without raising an error","relativedelta distinguishes relative offsets using plural kwargs from absolute field replacements using singular kwargs and allows combining both in a single operation","Unindexed and nth-instance weekday specifications navigate forward or backward to target weekdays relative to a reference date","Computing relativedelta between two datetimes decomposes the exact elapsed time into normalized calendar units that reconstruct the original date when added"],"goal":"Perform calendar unit arithmetic with dateutil.relativedelta.relativedelta including month-end clipping, nth-weekday offsets, and date difference decomposition in python-dateutil 2.9.0.post0","kind":"HOW","packages":["pkg:pypi/python-dateutil@2.9.0.post0"],"schemaVersion":1,"symbols":["dateutil.relativedelta.relativedelta"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/python-dateutil@2.9.0.post0"],"schemaVersion":1,"symbols":["dateutil.relativedelta.relativedelta"],"verifierAdapter":"python@1"}
python-dateutil==2.9.0.post0
six==1.17.0
import datetime
from dateutil.relativedelta import relativedelta, MO, FR
# 1. Calendar month/year addition clips day overflow to valid month boundaries
# Non-leap year: Jan 31 + 1 month -> Feb 28
dt_jan31_nonleap = datetime.datetime(2023, 1, 31, 10, 0)
dt_feb_nonleap = dt_jan31_nonleap + relativedelta(months=+1)
assert dt_feb_nonleap == datetime.datetime(2023, 2, 28, 10, 0), (
f"Expected 2023-02-28 10:00:00, got {dt_feb_nonleap}"
)
# Leap year: Jan 31 + 1 month -> Feb 29
dt_jan31_leap = datetime.datetime(2024, 1, 31, 10, 0)
dt_feb_leap = dt_jan31_leap + relativedelta(months=+1)
assert dt_feb_leap == datetime.datetime(2024, 2, 29, 10, 0), (
f"Expected 2024-02-29 10:00:00, got {dt_feb_leap}"
)
# Leap day: Feb 29 + 1 year -> Feb 28
dt_leap_day = datetime.datetime(2024, 2, 29, 12, 0)
dt_next_year = dt_leap_day + relativedelta(years=+1)
assert dt_next_year == datetime.datetime(2025, 2, 28, 12, 0), (
f"Expected 2025-02-28 12:00:00, got {dt_next_year}"
)
# 2. Relative offsets vs absolute field replacements
dt_base = datetime.datetime(2023, 5, 20, 14, 30)
# Plural kwargs add/subtract relative intervals
dt_offset = dt_base + relativedelta(months=+2, days=+5)
assert dt_offset == datetime.datetime(2023, 7, 25, 14, 30), (
f"Expected 2023-07-25 14:30:00, got {dt_offset}"
)
# Singular kwargs replace attributes absolutely
dt_replace = dt_base + relativedelta(month=12, day=25, hour=8)
assert dt_replace == datetime.datetime(2023, 12, 25, 8, 30), (
f"Expected 2023-12-25 08:30:00, got {dt_replace}"
)
# Combining relative offsets and absolute replacements
dt_combined = dt_base + relativedelta(months=+1, day=1)
assert dt_combined == datetime.datetime(2023, 6, 1, 14, 30), (
f"Expected 2023-06-01 14:30:00, got {dt_combined}"
)
# 3. Weekday navigation and nth-instance offsets
# Friday reference: weekday=FR or FR(+1) stays on Friday, FR(+2) moves to next Friday, FR(-2) moves to previous Friday
dt_fri = datetime.datetime(2023, 1, 6) # Friday
assert dt_fri + relativedelta(weekday=FR) == dt_fri
assert dt_fri + relativedelta(weekday=FR(+1)) == dt_fri
assert dt_fri + relativedelta(weekday=FR(+2)) == datetime.datetime(2023, 1, 13)
assert dt_fri + relativedelta(weekday=FR(-1)) == dt_fri
assert dt_fri + relativedelta(weekday=FR(-2)) == datetime.datetime(2022, 12, 30)
# Thursday reference: weekday=FR or FR(+1) moves forward to Friday, FR(-1) moves backward to previous Friday
dt_thu = datetime.datetime(2023, 1, 5) # Thursday
assert dt_thu + relativedelta(weekday=FR) == datetime.datetime(2023, 1, 6)
assert dt_thu + relativedelta(weekday=FR(+1)) == datetime.datetime(2023, 1, 6)
assert dt_thu + relativedelta(weekday=FR(-1)) == datetime.datetime(2022, 12, 30)
# Month boundary relative weekday calculations
first_mon = datetime.datetime(2023, 1, 1) + relativedelta(weekday=MO(+1))
assert first_mon == datetime.datetime(2023, 1, 2), f"Expected 2023-01-02, got {first_mon}"
last_fri = datetime.datetime(2023, 1, 31) + relativedelta(weekday=FR(-1))
assert last_fri == datetime.datetime(2023, 1, 27), f"Expected 2023-01-27, got {last_fri}"
# 4. Difference decomposition between two datetimes and exact reconstruction
dt1 = datetime.datetime(2024, 3, 15, 14, 30, 45)
dt2 = datetime.datetime(2020, 1, 10, 10, 15, 10)
rd = relativedelta(dt1, dt2)
assert (
rd.years == 4
and rd.months == 2
and rd.days == 5
and rd.hours == 4
and rd.minutes == 15
and rd.seconds == 35
), f"Unexpected decomposition: {rd}"
assert dt2 + rd == dt1, f"Reconstruction failed: {dt2} + {rd} != {dt1}"
# Reverse difference produces matching negative components
rd_rev = relativedelta(dt2, dt1)
assert (
rd_rev.years == -4
and rd_rev.months == -2
and rd_rev.days == -5
and rd_rev.hours == -4
and rd_rev.minutes == -15
and rd_rev.seconds == -35
), f"Unexpected reverse decomposition: {rd_rev}"
assert dt1 + rd_rev == dt2, f"Reverse reconstruction failed: {dt1} + {rd_rev} != {dt2}"
print("CONTRACT PASS: dateutil.relativedelta calendar arithmetic verified")