hank-format
Shared string formatting functions for standardizing names, dates, and times across the Hank AI stack.
pip install hank-format
Usage
from hank_format import as_name, as_date, as_date_str, as_datetime_str, as_time_str
as_name("Primary: John Doe") # 'DOE, JOHN'
as_name("Steven Hardman, APRN - CRNA") # 'HARDMAN, STEVEN, APRN, CRNA'
as_date("12/31/2020 (age 30 yrs)") # datetime.date(2020, 12, 31)
as_date_str("01012024") # '2024-01-01'
as_datetime_str("2020-12-31T23:59") # '2020-12-31 23:59:00'
as_datetime_str("23:59", precision="minute", default_date="2020-12-31") # '2020-12-31 23:59'
as_time_str("11:30 pm") # '23:30'
API
| Function | Returns | Notes |
|---|---|---|
as_name(value) |
str |
LAST, FIRST MIDDLE, SUFFIX, upper case. Strips Label: prefixes, [notes], (notes), *, and text after ;. |
is_date(value) |
bool |
True when a year, month, and day are present. |
has_time(value) |
bool |
True when an hour and minute are present. |
as_date(value) |
date | None |
Calendar date only. |
as_date_str(value) |
str |
YYYY-MM-DD or "". |
as_datetime(value, *, default_date=None) |
datetime | None |
Midnight when no time is present. Time-only input needs default_date. |
as_datetime_str(value, *, precision="second", default_date=None) |
str |
YYYY-MM-DD HH:MM:SS, or YYYY-MM-DD HH:MM with precision="minute". |
as_time(value) |
time | None |
Clock time only. |
as_time_str(value, *, precision="minute") |
str |
HH:MM, or HH:MM:SS with precision="second". |
Conventions:
- Inputs may be strings,
date,datetime,time, orNone. Other types raiseTypeError. - Object variants return
Noneand string variants return""when no usable value exists. - Returned values are timezone-naive and have no microseconds.
precisiontruncates, never rounds. - Any parsed date more than two days in the future rolls back 100 years, including four-digit years and year-less
MM/DD(12/31/45is 1945;12/26without a time is 1926 when today is 2026-10-08). This is a two-digit-year heuristic inherited from pdf-extractor; strip or validate far-future dates before calling if you need them intact. - Year-less
MM/DD HH:MMstrings take the current year, or the previous year if that would be in the future.
Migrating from pdf-extractor utils
| Legacy | hank-format |
|---|---|
as_name(s) |
as_name(s) (lists and vStr handling stay in pdf-extractor) |
as_date(v, date_only=True, as_dt=True) |
as_date(v) (returns date) |
as_date(v, date_only=True) |
as_date_str(v) |
as_date(v, as_dt=True) |
as_datetime(v) |
as_date(v) |
as_datetime_str(v) |
as_time(v, with_date=False) |
as_time_str(v) |
as_time(v, strict=True) |
as_datetime_str(v, precision="minute") if has_time(v) else "" |
as_time(v, default_date=d) |
as_datetime_str(v, precision="minute", default_date=d) if has_time(v) else "" |
as_time(v) |
as_datetime_str(v, precision="minute") if is_date(v) and has_time(v) else as_time_str(v) |
Legacy as_time returned "" for anything without a time; the new datetime
functions format a date-only value as midnight, hence the has_time guards.
Development
Requires uv.
uv sync # create .venv with Python 3.12 and the dev group
uv run pytest # tests with 100% coverage enforced
uv run ruff check . && uv run ruff format --check .
uv run pyright
uv build # sdist + wheel into dist/
Releasing
- Open a PR against
mainand add exactly one label:release:patch,release:minor, orrelease:major. - On merge, the
Releaseworkflow bumps__version__inhank_format/__init__.py, runs the tests, builds, commitsRelease vX.Y.Z, tags it, and pushes. A separatepublishjob then uploads the built artifacts to PyPI. - If only the
publishjob fails (for example, trusted publishing is not configured yet), fix the cause and re-run that failed job. Do not re-run the whole workflow: the version is already bumped and tagged, so a full re-run would bump it again.
One-time setup:
- On pypi.org, under the
hank-formatproject (or as a pending publisher), add a trusted publisher with ownerhank-ai, repositoryhank-format, workflowrelease.yml, environmentpypi. - In the GitHub repo settings, create an environment named
pypi. - The workflow pushes the version-bump commit to
mainwith the defaultGITHUB_TOKEN. Ifmainis protected, allow the token to bypass the rule or supply a PAT in aRELEASE_TOKENsecret and use it in the checkout step.
Metadata
Release files for hank-format 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hank_format-0.1.1.tar.gz | 10.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hank_format-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.6 kB
Release files / hank_format-0.1.1.tar.gz
| Download URL | hank_format-0.1.1.tar.gz |
|---|---|
| Size | 10.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f95b44ebafb64008bcf011622d0d7ce96a2bc3fa61d377a30bf8547142fe0040
|
|
BLAKE2b-256 checksum How to use checksums |
4910d3dd2fe2a884827c9c92e299a375a2d25063b5277a8fb00903538577a749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / hank_format-0.1.1-py3-none-any.whl
| Download URL | hank_format-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ad0ecff636c573409161e071a2fcf7c2a4e8cdbfe207c65a56cbe73d5a059238
|
|
BLAKE2b-256 checksum How to use checksums |
1e4cf397375a65c642c8615c272d1084f1d654e709f17cf9f1d8ca9cb362e4cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log