Prefix date parser
This is a helper class to parse dates with varied degrees of precision. For
example, a data source might state a date as 2001, 2001-4 or 2001-04-02,
with the implication that only the year, month or day is known. This library
will process such partial dates into a structured format and allow their
validation and re-formatting (e.g. turning 2001-4 into 2001-04 above).
The library does not support the complexities of the ISO 8601 and RFC 3339 standards including date ranges and calendar-week/day-of-year notations.
Installation
Install prefixdate using PyPI. It requires Python 3.11 or newer and has no
dependencies:
$ pip install prefixdate
Usage
The library provides a variety of helper functions to parse and format partial dates:
from prefixdate import parse, normalize_date, Precision
# Parse returns a `DatePrefix` object:
date = parse('2001-3')
assert date.text == '2001-03'
date = parse(2001)
assert date.text == '2001'
assert date.precision == Precision.YEAR
date = parse(None)
assert date.text is None
assert date.precision == Precision.EMPTY
# This will also be the outcome for invalid dates!
# Normalize to a standard string:
assert normalize_date('2001-1') == '2001-01'
assert normalize_date('2001-00-00') == '2001'
assert normalize_date('Boo!') is None
# This also works for datetimes:
from datetime import UTC, date, datetime
now = datetime.now(UTC).isoformat()
minute = normalize_date(now, precision=Precision.MINUTE)
# You can also feed in None, date and datetime:
normalize_date(datetime.now(UTC))
normalize_date(date.today())
normalize_date(None)
You can also use the parse_parts helper, which is similar to the constructor
for a datetime:
from prefixdate import parse_parts, Precision
date = parse_parts(2001, '3', None)
assert date.precision == Precision.MONTH
assert date.text == '2001-03'
Format strings
For dates which are not already stored in an ISO 8601-like string format, you
can supply one or many format strings for datetime.strptime. The format strings
will be analysed to determine how precise the resulting dates are expected to be.
from prefixdate import parse_format, parse_formats, Precision
date = parse_format('YEAR 2021', 'YEAR %Y')
assert date.precision == Precision.YEAR
assert date.text == '2021'
# You can try out multiple formats in sequence. The first non-empty prefix
# will be returned:
date = parse_formats('2021', ['%Y-%m-%d', '%Y-%m', '%Y'])
assert date.precision == Precision.YEAR
assert date.text == '2021'
Two-digit years
A %y format leaves the century open. strptime resolves it in a fixed
1969-2068 window, so a date outside of that lands in the wrong century. Pass
two_digit_year_base to choose the 100 years to read the year in yourself --
a base of 1926 covers 1926 to 2025:
from prefixdate import parse_format
date = parse_format('24-03', '%y-%m', two_digit_year_base=1926)
assert date.text == '2024-03'
date = parse_format('68-03', '%y-%m', two_digit_year_base=1926)
assert date.text == '1968-03'
Without a base year the strptime window applies and a warning is logged.
parse_formats takes the same argument.
Inspecting format strings
The helpers used to analyse formats are public, in case you want to apply the same reasoning before parsing:
from prefixdate import Precision, format_precision, has_two_digit_year
from prefixdate import resolve_two_digit_year
from datetime import datetime
# The precision a format string implies:
assert format_precision('%Y-%m') == Precision.MONTH
# Whether it reads the year as two digits:
assert has_two_digit_year('%y-%m') is True
# Move an already-parsed date into the century starting at a base year:
dt = resolve_two_digit_year(datetime(2024, 3, 1), 1926)
assert dt.year == 2024
Caveats
- Datetimes are always converted to UTC.
DatePrefix.dtkeeps its timezone and is aware (tzinfo=timezone.utc), whileDatePrefix.textreads as naive because the UTC offset sits past the precision the text is cut to. - Does not process milliseconds yet: fractional seconds are matched, but
discarded, so
DatePrefix.dt.microsecondis always0. - Does not process invalid dates, like Feb 31st.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file prefixdate-0.6.1.tar.gz.
File metadata
- Download URL: prefixdate-0.6.1.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
786ed09bbee47c2ec7eba71d175298c6f425f30ddb93ac5c826bac685521e038
|
|
| MD5 |
dfa80b30a174f42d7f2c36affe89469d
|
|
| BLAKE2b-256 |
4cda9d137eaf18a25ddb24f455f09ebb657eaf6e4ec56379edaf1f4de1ac9fd1
|
Provenance
The following attestation bundles were made for prefixdate-0.6.1.tar.gz:
Publisher:
build.yml on pudo/prefixdate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prefixdate-0.6.1.tar.gz -
Subject digest:
786ed09bbee47c2ec7eba71d175298c6f425f30ddb93ac5c826bac685521e038 - Sigstore transparency entry: 2381353180
- Sigstore integration time:
-
Permalink:
pudo/prefixdate@9ba83236180cfec15778ee83a56074dea48c9aa3 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/pudo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@9ba83236180cfec15778ee83a56074dea48c9aa3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file prefixdate-0.6.1-py3-none-any.whl.
File metadata
- Download URL: prefixdate-0.6.1-py3-none-any.whl
- Upload date:
- Size: 8.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
715ac5b027cfd382c50c746ecaf19dadb89d09b2b2356e170b09033bb5ad0d1c
|
|
| MD5 |
f7ef92a4e2251fe8600fb9a3ca816249
|
|
| BLAKE2b-256 |
bd98485bb34b41839ee84b7e2416846b0559b00756190e444528e09b721ebcdd
|
Provenance
The following attestation bundles were made for prefixdate-0.6.1-py3-none-any.whl:
Publisher:
build.yml on pudo/prefixdate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prefixdate-0.6.1-py3-none-any.whl -
Subject digest:
715ac5b027cfd382c50c746ecaf19dadb89d09b2b2356e170b09033bb5ad0d1c - Sigstore transparency entry: 2381353312
- Sigstore integration time:
-
Permalink:
pudo/prefixdate@9ba83236180cfec15778ee83a56074dea48c9aa3 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/pudo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@9ba83236180cfec15778ee83a56074dea48c9aa3 -
Trigger Event:
push
-
Statement type: