Dateparser turns a date written for a person into a datetime written for a program. It reads absolute dates in most formats, relative expressions such as "3 days ago" and "yesterday", timestamps, and month names in more than 200 language locales (project README).
Zyte released Dateparser, an open source library that parses human-readable dates, and in October 2020 we released version 1.0.0, a very important milestone. In this article, I'd like to introduce this library and share some insights into why it's so popular.
Dateparser was developed to make date extraction from HTML pages easier. Initially, it was used only by web scraping developers, but later it was quickly adopted by the wider community as well. It has been used for multiple applications like command-line tools, chatbots, etc.
1pip install dateparser1import dateparser
2
3dateparser.parse('15 March 2022')
4dateparser.parse('3 days ago')
5dateparser.parse('Marzo 15, 2022')Each of those returns a datetime, or None if the string could not be read as a date.
Zyte wrote it and maintains it. The first release on the Python Package Index was version 0.1.0 on 24 November 2014, version 1.0.0 followed on 29 October 2020, and the current release is 1.4.3, published 3 September 2026 (release history). It is free and open source under the BSD 3-Clause licence, and it supports Python 3.10 and above.
What does Dateparser handle that a hand-written parser does not?
When you are building software, dealing with date strings and parsing them can become very difficult and tedious: it is very hard to foresee all cases and build something that works efficiently. However, you should always look for ways to use existing solutions and avoid reinventing the wheel, and this is where Dateparser comes in handy: Dateparser can convert dates in all sorts of formats and locales to date time objects.
| What you find on a page | What a format-based parser does | What Dateparser returns |
|---|---|---|
15 March 2022 |
Works, given the right format string | A datetime |
15/03/2022 |
Ambiguous. Day 15 of month 3, or month 15? | A datetime, using DATE_ORDER or the locale |
03/15/2022 |
The same ambiguity, read the other way | A datetime |
2022-03-15 |
Works | A datetime |
3 days ago |
No format string matches this | A datetime, relative to a base you set |
yesterday |
No format string matches this | A datetime |
in 2 weeks |
No format string matches this | A future datetime |
Marzo 15, 2022 |
Fails unless you wrote Spanish month handling | A datetime |
August 14, 2015 EST |
Needs timezone handling you wrote | A datetime, timezone aware |
Tue, 15 Mar 2022 10:00:00 +0000 |
Needs a specific parser | A datetime |
Rows five to eight are the reason the library exists. Relative expressions and non-English month names are where a format-based approach stops, and both appear wherever a date is written the way a person would say it, such as listings and forums.
It would take a lot of time to create something so powerful from scratch, but instead, all you need to do is import Dateparser and use it.
How do I parse a date string in Python?
Using Dateparser is as simple as importing it and calling the parse() method:
1import dateparser
2
3dateparser.parse('20/11/2021')That returns datetime.datetime(2021, 11, 20, 0, 0). If the string cannot be read as a date, it returns None rather than raising, so check the result before using it.
Of course, you can do a lot more than this. But you can start using it without any heavy setup and without reading a lot of documentation.
The same string could be March or April. How do you tell it which?
You cannot resolve 03/04/2022 from the string. Nothing can. Either convention is valid and the string carries no information about which one was used, so the answer has to come from outside it.
Set DATE_ORDER, which "specifies the order in which date components year, month and day are expected while parsing ambiguous dates" (settings reference).
1dateparser.parse(
2 '15/03/2022',
3 settings={
4 'DATE_ORDER': 'DMY',
5 'TIMEZONE': 'UTC',
6 'RETURN_AS_TIMEZONE_AWARE': True,
7 },
8)Set it per source, not once for the whole project. A collection that reads a British listing and a United States listing in the same run needs two different values, and a single global setting silently misreads every ambiguous date from one of them.
What happens to "3 days ago" if you parse it a week later?
You get the wrong date, and nothing tells you.
A relative expression means nothing without a reference point. By default the reference is the moment you call parse, which is correct while you are reading the page and wrong the moment you store the raw string and parse it later. RELATIVE_BASE "allows setting the base datetime to use for interpreting partial or relative date strings" (settings reference).
So record the time you fetched the page, on the row, and pass it in.
1dateparser.parse(
2 '3 days ago',
3 settings={'RELATIVE_BASE': fetched_at},
4)A wrong reference point is invisible in the output. Every value is still a plausible date, measured from the wrong moment.
Which settings do you actually need?
Even if the interface is really simple, you can handle a lot of nuances by using the settings. You can pick a reference date, select the preferred date order, adjust the timezone configuration, decide how to handle incomplete dates, etc.
| Setting | What it decides | When you need it |
|---|---|---|
DATE_ORDER |
How to read an ambiguous numeric date | Any source that publishes dd/mm or mm/dd |
RELATIVE_BASE |
The moment "3 days ago" is counted from | Any source with relative dates, and any parsing done after the fetch |
TIMEZONE |
The timezone used to localise the result | Any source that publishes local times without an offset |
TO_TIMEZONE |
The timezone to convert the result into | When you normalise everything to one zone on the way in |
RETURN_AS_TIMEZONE_AWARE |
Whether to return an aware datetime when the string carries zone information | Almost always, if you store the result |
PREFER_DATES_FROM |
Whether an incomplete date resolves into the past or the future | Event listings, where an ambiguous date is usually upcoming |
STRICT_PARSING |
Return nothing if day, month or year is missing | When a partial date is worse than no date |
REQUIRE_PARTS |
Which components must be present for a result to be returned | When you need a full date and a bare year would corrupt the field |
The full list is in the settings reference.
Is there something you want to achieve? Take a look at the settings and you will probably find what you were looking for.
Where does Dateparser need help?
The library is free, and this page is written by the people who maintain it. Here is where it needs help.
Ambiguous numeric dates need a hint from you. Covered above. No parser resolves this on its own.
Timezones need a decision, not a default. A date with no zone is not a moment. Decide whether you are storing local time or normalising to one zone, and do it at collection, because reconciling a mixed column afterwards means re-reading every source to find out what each value meant.
Relative dates need a fetch time recorded. Also covered above, and it costs one column.
Speed. Trying many formats and locales is not free. Where you know a source's exact format and it does not vary, parsing it directly is faster. Use Dateparser for the sources whose format you cannot predict.
Language autodetection is a guess. If you know the source's language, pass it, rather than letting the library work it out for every string.
How do you use it inside a scraper?
Prefer a machine-readable date when the page publishes one. The HTML specification says the time element "represents its contents, along with a machine-readable form of those contents in the datetime attribute", and that the attribute's value must match a defined syntax such as 2011-11-18 (HTML Living Standard, the time element). A date in a time element or in the page's structured data was written for a program already and needs no parsing at all.
Use Dateparser for the visible date, which is the one written for a person and the one that varies by source and locale.
Normalise before you store. One format, one timezone rule, one column. A dataset with three date formats in one column cannot be sorted or compared, and fixing it later means re-reading every source.
Store the fetch time next to the date. It costs one column and it is the only thing that makes a relative date reproducible.
Store the raw string too. When a date turns out wrong six weeks later, the raw string is what tells you whether the parse was wrong or the page was.
When should you use strptime instead?
datetime.strptime |
Dateparser | |
|---|---|---|
| You supply | The exact format string | Nothing, or a few settings |
| Handles a varying format | No | Yes |
| Handles relative expressions | No | Yes |
| Handles non-English month names | Only with locale handling you write | Yes, across more than 200 locales |
| Speed | Faster | Slower, because it tries more |
| On an unreadable string | Raises | Returns None |
| Use it when | The format is fixed and you control the source | The format varies or is unknown |
Who else uses it?
| What | Figure | Source |
|---|---|---|
| Downloads in the trailing month | 37,182,241 | PyPI download statistics |
| Stars on the repository | 2,862 | GitHub repository API |
| Forks | 522 | GitHub repository API |
| Repository created | 24 November 2014 | GitHub repository API |
| Last change pushed | 22 September 2026 | GitHub repository API |
Four open source projects that list it as a dependency, each from the project's own dependency file:
| Project | What it does | The line in its dependency file |
|---|---|---|
| ArchiveBox | Self-hosted web archiving | dateparser>=1.2.0 in pyproject.toml |
| AWS SAM CLI | Command line tool for serverless applications | dateparser==1.4.2 in requirements/reproducible-linux.txt |
| Home Assistant CLI | Command line client for a home automation platform | dateparser = "^1.2.0" in pyproject.toml |
| Chaos Toolkit for Kubernetes | Resilience testing extension | dateparser>=1.2.0 in pyproject.toml |
Why is Dateparser so popular?
The people who maintain it give two reasons.
Good code comes with automated tests that provide good code coverage.
Few dependencies: Installing a package should never be a pain. Keeping a small set of well-maintained dependencies helps improve the user experience.
Where do you get help with Dateparser?
Accessible (and complete) documentation: If you need to achieve anything more complex than those common examples, or you need to understand something in-depth, you only need to visit the documentation, which carries the settings reference and the API.
Support: Anything is not working? Are you searching for a new feature? You can open an issue in the issue tracker on the repository, which also carries the source and the full locale list, and you will find support directly from the maintainers.
Building and maintaining open source projects is in our DNA, and we have been really proud to see this -little- project growing during the years!
If dates are one field in a larger collection problem, Zyte API returns article and product fields as typed values, dates included, which removes the parsing step for the sources it covers. Zyte sells that. Dateparser is free and open source either way.
FAQ
Q: What is Dateparser?
A: A Python library that turns date strings written for people into datetime objects. It reads numeric formats, written month names in more than 200 language locales, and relative expressions such as "3 days ago". Zyte wrote it and maintains it, and it is free and open source under the BSD 3-Clause licence.
Q: How do I parse a date string in Python?
A: import dateparser, then dateparser.parse(your_string). It returns a datetime, or None if it could not read the string.
Q: Can it handle "3 days ago" and "yesterday"?
A: Yes. Relative expressions are one of the two reasons the library exists. Pass RELATIVE_BASE in the settings if you are parsing after the fetch, or the result is counted from the wrong moment.
Q: How many languages does it support?
A: More than 200 language locales, according to the project README. The locale data comes from the Unicode Common Locale Data Repository.
Q: How do I stop it reading 03/04/2022 the wrong way?
A: Set DATE_ORDER in the settings, to DMY, MDY or YMD. No parser resolves that ambiguity from the string alone, so you tell it which convention the source uses, per source rather than once globally.
Q: Why does it return None?
A: Because it could not read the string as a date. The string may carry extra text around the date, or it is in a format or locale the parser did not recognise. Print what you passed in before assuming the library failed.
Q: Dateparser or datetime.strptime?
A: strptime when the format is fixed and you control the source, because it is faster and exact. Dateparser when the format varies or is unknown.
Q: Does it handle timezones?
A: Yes, through TIMEZONE, TO_TIMEZONE and RETURN_AS_TIMEZONE_AWARE. Decide the rule at collection. A date with no timezone is not a moment, and a column with mixed rules cannot be fixed later without re-reading every source.
Q: Which Python versions does it support?
A: Python 3.10 and above, according to the project README.
Q: Is it free to use commercially?
A: Yes. It is published under the BSD 3-Clause licence.





