mrkeyoor.com_
Sat 19 Sept 23:45 UTC
PyPIUtilsupdated 19 Sept 2026

python-dateutil review

python-dateutil 2.9.0.post0 extends the standard `datetime` module in four distinct areas: permissive string parsing, calendar-relative arithmetic, iCalendar recurrence rules, and additional timezone implementations. `parser.isoparse` handles ISO input, while `parser.parse` accepts much looser text. `relativedelta` moves by calendar months and years instead of fixed seconds. Version 2.9.0 updates bundled timezone data to 2024a, lazily exposes submodules on modern Python, and removes a Python 3.12-deprecated call; post0 fixes generated version-file compatibility.

Verdict

python-dateutil 2.9.0.post0 installed in 0.2 seconds as 2 packages using 1 MB, with a 0.02-second import and 0 audit findings in our sandbox; keep it for recurrence rules, calendar deltas, or deliberately flexible parsing. Standard-library ISO parsing and zoneinfo are better defaults for narrow modern contracts.

We installed it

Lab card: what happened when we installed python-dateutilScreenshot of python-dateutil documentation
Install✓ · 0.2s2 packages on disk · 1 MB
Importimport dateutil in 0.02s · pure Python · requires Python !=3.0.*,!=3.1.*,!=3.2.*,>=2.7
Known vulns0(pip-audit)

Answers from our run

Does python-dateutil install cleanly?

Yes. In a fresh container with an empty cache, pip install python-dateutil finished in 0.2s, leaving 2 packages and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does python-dateutil need to run?

Python !=3.0.,!=3.1.,!=3.2.*,>=2.7, and nothing compiled: it is pure Python. In our run import dateutil succeeded in 0.02s.

python-dateutil or pendulum: which should you use?

pendulum: Choose it for its own timezone-aware datetime type, duration API, and opinionated higher-level helpers. python-dateutil 2.9.0.post0 installed in 0.2 seconds as 2 packages using 1 MB, with a 0.02-second import and 0 audit findings in our sandbox; keep it for recurrence rules, calendar deltas, or deliberately flexible parsing.

When should you not use python-dateutil?

The input contract is ISO 8601 supported by datetime.fromisoformat; the standard library is narrower and adds no dependency.

API stability5/5parser.parse, parser.isoparse, relativedelta, rrule, rrulestr, and dateutil.tz have retained familiar call patterns through a long 2.x line. Version 2.9.0 adds lazy submodule access and Python 3.12 compatibility without replacing those APIs. Parsing bug fixes can still adjust which permissive strings succeed, so accepted production formats belong in tests rather than relying on undocumented tolerance.
Docs4/5The stable documentation explains every parser option, relativedelta's component ordering, recurrence constructors and constants, timezone helpers, Easter calculation, and API details with examples. It even clarifies the limited month-end clamp condition. Guidance on hostile input, ambiguous locale policy, stale bundled timezone data, and choosing standard-library replacements is less prominent than the feature reference.
Maintenance2/5PyPI still lists 2.9.0.post0 from March 2024, while GitHub showed a May 19, 2026 push, 475 open issues and pull requests, 2,632 stars, and an unarchived repository. Source work continues, but no newer stable package has followed the Python 3.12 and tzdata 2024a release. The mature API lowers feature pressure while leaving fixes and timezone freshness exposed to a slow release cycle.
Ecosystem5/5The provided weekly snapshot records 284,309,467 PyPI downloads, and the project has 2,632 GitHub stars. dateutil is pulled transitively by major data, plotting, HTTP, and scheduling stacks. Standard-library datetime parsing and zoneinfo have absorbed part of its old role, yet relativedelta and RFC-style recurrence remain distinct enough to keep it deeply embedded.

Discussed on

  1. hnCode that breaks 2 or 3 times every month45 points

Use it if

  • Several documented date formats must be accepted and `datetime.fromisoformat` cannot parse all of them.
  • Month, year, weekday, or month-end arithmetic must follow calendar rules rather than elapsed seconds.
  • The application consumes or generates RFC 5545-style recurrence rules with rrule or rrulestr.
  • Existing code already exchanges dateutil tzinfo, parser, or relativedelta objects across package boundaries.
Skip it if

Setup reality

We installed python-dateutil 2.9.0.post0 in a fresh Python 3.12 Bookworm sandbox in 0.2 seconds. It left 2 packages using 1 MB, and pip-audit reported 0 known vulnerabilities. import dateutil took 0.02 seconds. The distribution is pure Python, declares 1 direct dependency, and reports a dual license. It has no py.typed marker. Package metadata still permits Python 2.7 while excluding Python 3.0 through 3.2.

Prefer datetime.fromisoformat or parser.isoparse for a fixed wire format. General parser.parse fills omitted parts from a default datetime, so an absent day or time can inherit a value the caller never supplied. Pass an explicit default, keep fuzzy parsing off unless required, and define dayfirst plus yearfirst rules for numeric input. Version 2.9.0's lazy submodule imports change convenience, not parsing policy.

Timezone abbreviations are ambiguous. Supply a restricted tzinfos mapping and turn UnknownTimezoneWarning into an error when aware results are mandatory. Parsing text without an offset still returns a naive datetime. Version 2.9.0 bundles tzdata 2024a, which is now older than many system databases; standard-library zoneinfo can use the deployment's current IANA data for new internal code.

relativedelta applies absolute and relative pieces in a defined order, then applies weekday selection. Test January 31, leap days, and daylight-saving transitions. Recurrence iterators may be unbounded; external rules need a count, an until date, or an application-side limit. RFC recurrence skips invalid dates rather than applying relativedelta's month-end clamping, so the two APIs can produce different schedules from similar-looking requirements.

Patterns

Parse a defined ISO value parse-iso-timestamp

from dateutil.parser import isoparse

created_at = isoparse('2026-08-26T14:30:00+05:30')

Use isoparse for ISO input. The general parser accepts many extra forms that a wire protocol may not permit.

Parse a loose date with a fixed default parse-known-text

from datetime import datetime
from dateutil.parser import parse

default = datetime(2000, 1, 1, 0, 0, 0)
value = parse('4th of July 2026', default=default)

Missing components come from `default`; set it explicitly so today's date or an inherited time cannot leak into the result.

Choose day-first parsing set-numeric-date-order

from dateutil.parser import parse

value = parse('10/09/2026', dayfirst=True, yearfirst=False)

dayfirst and yearfirst are application policy. They do not detect the user's locale from the string.

Resolve approved abbreviations map-timezone-name

from dateutil import parser, tz

zones = {
    'IST': tz.gettz('Asia/Kolkata'),
    'CST': tz.gettz('America/Chicago'),
}
value = parser.parse('2026-08-26 14:30 IST', tzinfos=zones)

Abbreviations such as IST and CST have multiple meanings, so accept only mappings defined by the application.

Move from month end add-calendar-month

from datetime import date
from dateutil.relativedelta import relativedelta

result = date(2026, 1, 31) + relativedelta(months=1)
# 2026-02-28

relativedelta clamps when the corresponding day does not exist; it does not treat one month as a fixed duration.

Get the final Friday find-month-weekday

from datetime import date
from dateutil.relativedelta import FR, relativedelta

last_friday = date(2026, 8, 1) + relativedelta(
    day=31, weekday=FR(-1)
)

The absolute day is applied before the weekday adjustment, following relativedelta's documented component order.

Express a difference in calendar units measure-calendar-gap

from datetime import date
from dateutil.relativedelta import relativedelta

gap = relativedelta(date(2026, 8, 26), date(2020, 2, 29))
print(gap.years, gap.months, gap.days)

Calendar years, months, and days do not represent a fixed number of elapsed seconds.

List four weekly occurrences generate-bounded-recurrence

from datetime import datetime
from dateutil.rrule import MO, WE, WEEKLY, rrule

occurrences = list(rrule(
    WEEKLY,
    byweekday=(MO, WE),
    count=4,
    dtstart=datetime(2026, 8, 24),
))

Always bound external recurrence rules with count, until, or an application limit before materializing them.

Alternatives

PackageRegistryPick it when
pendulumPyPIChoose it for its own timezone-aware datetime type, duration API, and opinionated higher-level helpers.
dateparserPyPIChoose it for multilingual month names and relative natural-language phrases such as dates expressed in human terms.
arrowPyPIChoose it when a chainable wrapper and human-readable formatting are more important than RFC recurrence rules.

More utils guides

lru-cache · type-fest · ajv · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.