Data conversion/normalization in a nutshell
Project description
convi-lab
Data conversion and normalization utilities. The current focus is datetime
parsing — turning messily formatted date/time strings into a single
normalized "YYYY-MM-DD HH:MM:SS" output — with fuzzy name matching as a
first-class primitive that powers the date logic and is exposed for general use.
Installation
pip install convi-lab
Runtime dependencies: logger-lab >= 0.1.1, rapidfuzz >= 3.0.0
Quick start
from convi_lab import convert_date_time, convert_name, DAYS, MONTHS
# Datetime normalization
convert_date_time("Tuesday 12:30 PM") # "2026-05-13 12:30:00"
convert_date_time("17 Jul - 02:00 PM") # "2026-07-17 14:00:00"
convert_date_time("12.04.2025 22:15") # "2026-04-12 22:15:00"
convert_date_time("Today 09:00") # "2026-05-09 09:00:00"
# Fuzzy name matching
convert_name("Mon", DAYS) # "Monday"
convert_name("Jul", MONTHS) # "July"
convert_name("Celts", ["Boston Celtics", "Brooklyn Nets"]) # "Boston Celtics"
Supported datetime formats
All formats accept an optional AM/PM suffix (case-insensitive).
Spaces between components are stripped automatically.
| Format | Example input | Parsed as |
|---|---|---|
dd/mm HH:MM |
"12/04 22:15" |
April 12, 22:15 |
dd/mm/yy HH:MM |
"12/04/25 10:15 PM" |
April 12 2025, 22:15 |
dd.mm.yyyy HH:MM |
"12.04.2025 12:15 pm" |
April 12 2025, 12:15 |
Day HH:MM |
"Tuesday 12:30" |
Next Tuesday, 12:30 |
Today/Tomorrow HH:MM |
"Today 14:30" |
Today at 14:30 |
ddMon[-]HH:MM |
"17 Jul - 02:00 PM" |
July 17, 14:00 |
Year boundary rule: if the resolved date is in the past (date only, not time), the year is automatically bumped to the next calendar year.
Day rule: weekday names always resolve to the next occurrence. If
today is Tuesday and you pass "Tuesday 12:30", the result is next
Tuesday, not today.
Error handling
All exceptions inherit from LabError. You can catch broadly or precisely:
from convi_lab import convert_date_time, LabError, ParserError
# convert_date_time is the safe boundary — it returns "" on any failure
result = convert_date_time("garbage input")
assert result == ""
# Call process_patterns directly to get typed exceptions
from convi_lab import process_patterns
from convi_lab.conversion_kernel.utils import remove_spaces
try:
dt = process_patterns(remove_spaces("17 Jly - 02:00"))
except ParserError as exc:
print(f"Parse failed: {exc}")
except LabError as exc:
print(f"Conversion failed: {exc}")
Exception hierarchy
LabError
├── ParserError
│ ├── PatternMatchError no pattern matched the input
│ ├── DayResolutionError weekday/relative-day string unresolvable
│ ├── MonthResolutionError month name unresolvable
│ └── DateComponentError numeric date fragment malformed
└── ConversionError
├── ClockFormatError HH:MM[AM|PM] string failed to parse
├── FuzzyMatchError rapidfuzz returned no result
└── InvalidInputError bad type or empty string at entry point
Fuzzy name matching
convert_name is a general-purpose utility — pass any query and any
reference list:
from convi_lab import convert_name
teams = ["Atlanta Hawks", "Boston Celtics", "Brooklyn Nets"]
convert_name("A. Hawks", teams) # "Atlanta Hawks"
convert_name("Nets", teams) # "Brooklyn Nets"
countries = ["United States", "United Kingdom", "Australia"]
convert_name("USA", countries) # "United States"
convert_name("Aus", countries) # "Australia"
It raises FuzzyMatchError if rapidfuzz finds nothing, so you always
get a typed failure rather than a silent empty string.
Roadmap
The library is intentionally small today. Planned additions:
Number and currency
- Locale-aware number parsing —
"1.234,56"(DE) /"1,234.56"(US) →float - Currency string normalization —
"$1,200.00","€ 1.200"→Decimal
Identity and contact data
- Phone number normalization —
"+1 (800) 555-0100","08001234"→ E.164 format - Email normalization — lowercase, strip display names, validate structure
- Name normalization —
"DR. JOHN A. SMITH"→{"prefix": "Dr.", "first": "John", "last": "Smith"}
Units and measurements
- Temperature —
"98.6 F"/"37 C"/"310 K"→ normalized(value, unit) - Distance — km, miles, nautical miles with conversion helpers
- Weight — kg, lb, oz
Geolocation
- Country/locale normalization —
"USA","US","United States of America"→ ISO 3166-1 alpha-2 - Timezone string normalization —
"EST","Eastern Time","America/New_York"→ IANA key
Data quality
- Boolean parsing —
"yes","true","1","on","enabled"→bool - Null/empty detection —
"N/A","none","–",""→None - Whitespace and encoding normalization — strip invisible Unicode, normalize line endings
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 convi_lab-0.1.0.tar.gz.
File metadata
- Download URL: convi_lab-0.1.0.tar.gz
- Upload date:
- Size: 17.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6f0a202ab8966ccf8329c7a3fbf67258e70ebae1617c5bb83d89e8a4c02b3ab
|
|
| MD5 |
30be83a2e54f3a6c6b255fd4d9bd6190
|
|
| BLAKE2b-256 |
7e343e56f24a0eaab1e83096fe43f255a7c3f343e6921d3d9738db8f2c53aedd
|
File details
Details for the file convi_lab-0.1.0-py3-none-any.whl.
File metadata
- Download URL: convi_lab-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7a2c42ced276366a6025216d6843875c229ebecd41ea0436e058edf284142bb
|
|
| MD5 |
adc015c5de7dd2de24f3f0a16cad3d26
|
|
| BLAKE2b-256 |
f1b4ec27f54a9d8182719d0bcdb9851e52a93d0d7fa27774acf70f236e8f9339
|