parsedatetime
Parse human-readable date and time strings like tomorrow or in 5 minutes into structured Python datetimes
Repository Health
Technical Analysis
parsedatetime is a Python library that converts natural-language date and time phrases such as “tomorrow”, “next friday”, “in 5 minutes”, or “3 weeks ago” into structured time tuples or Python datetime objects. It originated from date/time parsing code Mike Taylor built for the Chandler personal information manager project and has been maintained as a standalone open-source library since 2004.
The library exposes a Calendar class as its main entry point, with parse(), parseDT(), parseDate(), and parseDateText() methods covering natural-language phrases, ISO-style dates, and long-form text respectively. It ships locale data for English (US/Australian), German, French, Spanish, Dutch, Portuguese, and Russian, and integrates with pytz for timezone-aware output.
What You Get
- A Calendar class with parse(), parseDT(), parseDate(), and parseDateText() methods for different input styles
- Support for relative and fuzzy natural-language phrases (“tomorrow”, “in 5 minutes”, “3 weeks ago”)
- Locale data for English (US, Australian), German, French, Spanish, Dutch, Portuguese, and Russian
- Optional pytz-based timezone handling via parseDT()
- A Constants class for customizing parsing behavior such as the two-digit-year birthday epoch
Common Use Cases
- Accepting free-text due dates or reminders in a task manager or to-do app
- Parsing natural-language date filters typed into a search box (“show me events next week”)
- Normalizing user-submitted date strings from forms or chat interfaces into datetime objects
- Building CLI tools that accept human-friendly date arguments instead of strict ISO formats
Under The Hood
Architecture - The library centers on a single Calendar class (parsedatetime/init.py, ~2,800 lines) that owns a Constants instance (ptc) holding locale-specific regex tables, keywords, and format strings loaded from parsedatetime/pdt_locales/. Calendar.parse() walks the input string against these regex grammars for relative phrases, weekdays, and unit offsets, then resolves them against a sourceTime baseline (defaulting to now) to produce a 9-field time_struct plus a pdtContext (context.py) describing which fields were actually set. parseDT() wraps parse() and applies pytz tzinfo; parseDate() and parseDateText() are narrower entry points that bypass the full NLP grammar for stricter date formats. Locale selection runs through pdt_locales/base.py plus per-language modules (en_US.py, de_DE.py, fr_FR.py, etc.), optionally backed by ICU (pdt_locales/icu.py) when PyICU is installed.
Tech Stack - Pure Python 3 (99.6% of the codebase), with zero required runtime dependencies beyond the standard library; optional integrations with pytz for timezone-aware output and PyICU/icu4c for richer locale calendar data. Packaging uses classic setuptools, with setup.py extracting version and author metadata directly from dunder attributes in parsedatetime/init.py. Development tooling is pipenv + tox + CircleCI, defined via Pipfile, pytest.ini, and .circleci/.
Code Quality - The tests/ directory contains 22 TestXxx.py modules (TestSimpleDateTimes, TestComplexDateTimes, TestErrors, TestRanges, plus dedicated per-locale suites for French, German, Russian, and Australian English) run via pytest, giving fairly thorough behavioral coverage of the parsing grammar. The core init.py is a single large monolith mixing constants, regex tables, and the Calendar class rather than being split into smaller modules, which raises the bar for extending the grammar; naming is descriptive but there is minimal type-hinting throughout, consistent with code that predates modern typing conventions.
API Design - The public surface is compact and beginner-friendly: Calendar().parse("tomorrow") is the entire quick-start, documented directly in the README and examples/basic.py. A backward-compatible shim (parsedatetime/parsedatetime.py) preserves older import paths. The four-method split (parse/parseDT/parseDate/parseDateText) does require users to learn which entry point fits their input style, and the raw parse() return value (a time-tuple plus a context flag) is less ergonomic than a plain datetime unless callers reach for parseDT() instead.