Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Chrono Python (v3)

A natural language date parser.

A Python version of chrono (originally written in Javascript), featuring a recent design and refined architecture. It identifies and extracts dates, times, and relative date expressions from free text without relying on external dependencies.

Features & Supported Formats

  • Today, Tomorrow, Yesterday, Last Friday, etc.
  • 17 August 2013 - 19 August 2013
  • This Friday from 13:00 - 16:00
  • 5 days ago, 2 weeks from now
  • 2014-11-30T08:15:30-05:30
  • Multi-language support: English (en), Japanese (ja), French (fr), Italian (it), and Chinese (zh).

Difference from Chrono v2 (Javascript)

While chrono-python retains Chrono's core parsing logic and multi-locale design, it introduces a refined architecture tailored for Python:

  • Separation of Date-Time & Reference Abstractions: Decouples absolute moments, calendar component representations, and relative shifts using DateTimeMoment, CivilTimeMoment, and ReferenceMoment, rather than relying on JavaScript Date / ParsingComponents.
  • Explicit Precision System: Tracks the exact level of granularity of every parsed expression (YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, etc.) via DateTimePrecision.
  • Descriptive Parser Naming: Uses positional naming conventions (e.g., MonthNameBeforeDate, MonthNameAfterDate) rather than endianness terms.

Installation

Install using pip:

pip install chrono-python

Usage

Simply pass a string to chrono.parse or chrono.parse_date:

import chrono_python as chrono

# parse() returns a list of ParsedResult objects
results = chrono.parse("An appointment on Sep 12-13")
# [<ParsedRangeResult "Sep 12-13" : 2026-09-12 12:00:00 -> 2026-09-13 12:00:00>]

# parse_date() returns a standard Python datetime.datetime object (or None)
date = chrono.parse_date("12 June 2026")
# datetime.datetime(2026, 6, 12, 12, 0)

Reference Dates

Relative date expressions like "Friday", "tomorrow", or "2 days ago" depend on when they are mentioned. Pass a reference datetime to resolve relative expressions against a specific point in time:

import datetime
import chrono_python as chrono

ref_date = datetime.datetime(2012, 8, 23, 12, 0)

# "Friday" following Aug 23, 2012
chrono.parse_date("Friday", reference=ref_date)
# datetime.datetime(2012, 8, 24, 12, 0)

# "2 days ago" relative to Aug 23, 2012
chrono.parse_date("2 days ago", reference=ref_date)
# datetime.datetime(2012, 8, 21, 12, 0)

Locale Support

chrono.parse defaults to international English. To parse text in other supported languages, access the locale's casual or strict configuration:

import chrono_python as chrono

# Japanese
chrono.ja.casual.parse("明日5時に")

# French
chrono.fr.casual.parse("demain à 15h")

# Italian
chrono.it.casual.parse("domani alle 15:00")

# Chinese
chrono.zh.casual.parse("明天下午5点")

You can also import locale submodules directly:

from chrono_python.locales import ja, fr

results = ja.casual.parse("2026年8月2日")

Casual vs. Strict Modes

Most locales provide two parsing configurations:

  • casual: Parses informal/casual terms (e.g., "today", "tomorrow", "next week", "10m ago") in addition to standard date formats.
  • strict: Parses only formal/strict date expressions (e.g., ISO formats, explicit slash dates, exact month-day patterns).
import chrono_python as chrono

# Casual mode parses relative words
chrono.en.casual.parse("today")   # Returns parsed result for today

# Strict mode ignores informal words
chrono.en.strict.parse("today")   # Returns []

Advanced Usage

Parsed Results and Moments

When calling chrono.parse(text), Chrono returns a list of ParsedResult objects (or ParsedRangeResult for date ranges).

ParsedResult & ParsedRangeResult

A ParsedResult represents a matched date expression within the input text and provides the following properties:

  • index: The zero-based starting character position of the match in the input string.
  • text: The exact substring matched from the input.
  • start (or moment): The Moment object representing the parsed start date and time.
  • datetime(): A convenience method returning the Python datetime.datetime object of the start moment.
  • precision(): A convenience method returning the DateTimePrecision enum value of the start moment.

When a date range is parsed (e.g., "August 10 to August 15, 2026"), Chrono returns a ParsedRangeResult which includes an additional property:

  • end: The Moment object representing the parsed end date and time.
import chrono_python as chrono

results = chrono.parse("Meeting from 9:00am to 11:30am on Friday")
result = results[0]

print(result.index)        # 8
print(result.text)         # "9:00am to 11:30am on Friday"
print(result.datetime())   # 2026-08-21 09:00:00
print(result.precision())  # DateTimePrecision.MINUTE

if isinstance(result, chrono.ParsedRangeResult):
    print("Start:", result.start.datetime())  # 2026-08-21 09:00:00
    print("End:  ", result.end.datetime())    # 2026-08-21 11:30:00

The Moment Abstraction

Moment is the core abstraction representing an extracted point in time. It provides a consistent interface across different kinds of date expressions:

  • moment.datetime() -> datetime.datetime: Converts the moment into a standard Python datetime.datetime object. For date-only expressions (where no time is specified), the time component defaults to 12:00 PM (noon).
  • moment.precision() -> DateTimePrecision: Returns the level of precision of the extracted moment (see Date & Time Precision).

Under the hood, Chrono uses specialized Moment subclasses:

  • DateTimeMoment: Represents an absolute point in time with a fixed precision.
  • ReferenceMoment: Represents a relative duration offset from a reference date (e.g., "5 days ago" or "in 2 weeks").
  • CivilTimeMoment: Represents a calendar-component date/time tracking which components were explicitly stated (certain) vs. inferred (implied).

Civil Time and Components

Natural language date expressions rarely specify all date and clock fields. When parsing "August 17 at 8:00", the month, day, hour, and minute are explicitly stated, but the year is inferred from the reference date.

Chrono represents this with CivilTimeMoment, separating fields into known (certain) values and implied values:

  • Certain / Known Values: Components explicitly found in the parsed text (e.g., "August" -> month 8, "17" -> day 17).
  • Implied Values: Components inferred from context, the reference date, or sensible defaults (e.g., the reference year or noon for date-only inputs).

You can import CivilTimeComponent from chrono_python.common.types to query individual fields and check certainty:

import chrono_python as chrono
from chrono_python.common.types import CivilTimeComponent

results = chrono.parse("August 17 at 8:00")
moment = results[0].start

# Query component values (accepts enum or string)
print(moment.get(CivilTimeComponent.MONTH))  # 8
print(moment.get(CivilTimeComponent.DAY))    # 17
print(moment.get(CivilTimeComponent.HOUR))   # 8
print(moment.get(CivilTimeComponent.YEAR))   # 2026 (inferred from reference)

# Check certainty (whether it was explicitly mentioned in text)
print(moment.is_certain(CivilTimeComponent.DAY))   # True
print(moment.is_certain(CivilTimeComponent.YEAR))  # False

# List all explicitly stated components
print(moment.list(only_certain=True))
# [<CivilTimeComponent.MONTH: 'month'>, <CivilTimeComponent.DAY: 'day'>, <CivilTimeComponent.HOUR: 'hour'>, <CivilTimeComponent.MINUTE: 'minute'>]

# Helper query and validation methods
print(moment.is_only_date())               # False (contains time)
print(moment.is_date_with_unknown_year())  # True (month/day known, year implied)
print(moment.is_valid_date())              # True (validates calendar constraints & leap days)

Date & Time Precision

Unlike standard Python datetime objects—which require year, month, day, hour, minute, and second, implicitly defaulting missing fields—Chrono preserves the exact granularity of the user's input through the DateTimePrecision enum.

Every ParsedResult and Moment provides .precision() indicating how fine-grained the matched input text was.

Precision Levels

DateTimePrecision defines the following levels in increasing order of granularity:

Level Value Example Expression Description
YEAR 10 "in 2026" Only the year was specified
MONTH 20 "August 2026" Specified down to the month
WEEK 30 "next week" Specified as a week
DAY 40 "August 17, 2026", "today" Specified down to the day (date only)
HOUR 50 "at 6pm", "18:00" Specified down to the hour
MINUTE 60 "at 18:40", "8:15 AM" Specified down to the minute
SECOND 70 "18:40:25" Specified down to the second
MILLI_SECOND 80 "18:40:25.123" Specified down to milliseconds

Using Precision in Your Application

You can use precision values to determine whether the user provided a specific time of day or only a general date:

import chrono_python as chrono
from chrono_python.types import DateTimePrecision

results = chrono.parse("Let's meet on August 17 at 18:40")
result = results[0]

# Check if the user specified time-of-day information
if result.precision().value >= DateTimePrecision.HOUR.value:
    print(f"Specific meeting time: {result.datetime().strftime('%Y-%m-%d %H:%M')}")
else:
    print(f"All-day date: {result.datetime().strftime('%Y-%m-%d')}")

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chrono_python-3.0.0.dev0.tar.gz (161.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chrono_python-3.0.0.dev0-py3-none-any.whl (239.0 kB view details)

Uploaded Python 3

File details

Details for the file chrono_python-3.0.0.dev0.tar.gz.

File metadata

  • Download URL: chrono_python-3.0.0.dev0.tar.gz
  • Upload date:
  • Size: 161.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for chrono_python-3.0.0.dev0.tar.gz
Algorithm Hash digest
SHA256 43210bb09eb11dffd29eee592209290ac41617230f04f28261d817ecc332394b
MD5 0b45db8c3354bee9bd0fdf4ec6e535d3
BLAKE2b-256 717cfb1f35bc78f1bdc90ecd28975bfea3855f5a6624d1a798b6fb89f088d8b3

See more details on using hashes here.

File details

Details for the file chrono_python-3.0.0.dev0-py3-none-any.whl.

File metadata

  • Download URL: chrono_python-3.0.0.dev0-py3-none-any.whl
  • Upload date:
  • Size: 239.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for chrono_python-3.0.0.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 c312f31358a3cbce2e908b713767f75282d2e6dfda292f325e208496d5187c04
MD5 e5ffb67aa06c64538eef7550ba3816ed
BLAKE2b-256 05bbaef1475235f65b1e5a4b871af4d7be7c4ba842aac63f430b841cea06a1f1

See more details on using hashes here.

Release history Release notifications | RSS feed

3.0.0

2 files

This release

3.0.0.dev0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page