Skip to main content

Best practices

Construct once, parse many

Build a single DateParser per process or worker. Pattern generation and indexing happen in __init__; parse() is the cheap path.

parser = qddate.DateParser(languages=["en", "de"])
dates = [parser.parse(row) for row in rows]

Restrict languages when you know them

Pass languages= for crawls that stay in one locale or a small set. This is faster and avoids month-name collisions across languages.

Treat None as "no date"

Do not wrap parse() in try/except for normal misses. Invalid input and unsupported formats return None. Catch ValueError only around constructor calls with untrusted languages= values.

Keep dates left-aligned

Strip leading labels in the scraper, not in qddate:

text = raw.lstrip()
# or cut a known prefix such as "Published: "

qddate ignores trailing noise; it does not search the middle of a sentence.

Prefer explicit formats upstream

When you control the producer, emit ISO-8601 (YYYY-MM-DD). qddate still helps for third-party HTML; it is not a substitute for a stable date field in your own APIs.

Do not use qddate for relative dates

"yesterday", "2 days ago", and timezone-aware scheduling belong in dateparser or dateutil. Mixing libraries by concern is expected: qddate for bylines, another parser for user-typed relative phrases. See when to use.

Add patterns with tests, not one-off regexes

New formats should land as named entries in qddate/patterns/ plus fixtures in tests/. After adding them, regenerate the language catalog:

python scripts/generate_pattern_docs.py

See adding languages.