Temporal Expression Normalization for spaCy (TeNs)
Temporal Expressions Normalization spaCy (TeNs) is a powerful pipeline component for spaCy that seamlessly identifies and parses date entities in text. It leverages the Temporal Expressions Normalization Framework to recognize a wide variety of date formats using an extensive set of regular expressions (RegEx), ensuring robust and adaptable date extraction across diverse textual sources.
Unlike conventional solutions that primarily focus on well-structured date formats, TeNs excels in handling real-world text by identifying not only standard date representations but also abbreviated, informal, or even misspelled temporal expressions. This makes it particularly effective for processing noisy or unstructured data, such as historical records, user-generated content, and scanned documents with OCR inaccuracies.
Moreover, TeNs is designed to integrate seamlessly into existing NLP pipelines, allowing for enhanced temporal information processing in tasks such as event extraction, timeline construction, and knowledge graph population. By providing a flexible and accurate approach to temporal data normalization, it significantly improves the quality and reliability of date-related information extracted from text.
Table I. Types of temporal expressions which can be processed
| Type of Temporal Expressions | Examples of Temporal Expressions* |
|---|---|
| dates |
YMD: 1881-08-31; 1857 mai 10; etc. DMY: 09.11.1518; 1 noiembrie 1624; etc. MY: ianuarie 632; etc. |
| timespans |
centuries: s:; sc; se.; sec; sec.; secol; secolele; secolul; sex. millenniums: mil; mil.; mileniul; mileniului; mileniile |
| years | 77; 78; 1652; [1873]; aproximativ 1834; cca. 1420; etc. |
Getting started
Prerequisites
- Python 3.9-3.12
- JRE 11-17
- spaCy >=3.8.7,<4.0.0
- py4j 0.10.9.9
- langdetect 1.0.9
Install
pip install temporal-normalization-spacy
Supported languages
Use with spaCy library
Importing Modules & Defining Constants
import subprocess
import spacy
from temporal_normalization.commons.print_utils import console
LANG = "ro"
MODEL = "ro_core_news_sm"
TEXT_RO = ("Sec al II-lea a.ch. a fost o perioadă de mari schimbări. "
"În secolul XX, tehnologia a avansat semnificativ. "
"Sec. 21 este adesea asociat cu globalizarea rapidă.")
Adding the Component to spaCy Pipeline
# Display a warning if the language of the text is not Romanian.
console.lang_warning(TEXT_RO, target_lang=LANG)
try:
# Load the spaCy model if it has already been downloaded
nlp = spacy.load(MODEL)
except OSError:
console.warning(f'Started downloading {MODEL}...')
# Download the Romanian model if it wasn't already downloaded
subprocess.run(["python3", "-m", "spacy", "download", MODEL])
# Load the spaCy model
nlp = spacy.load(MODEL)
# Add "temporal_normalization" component to the spaCy pipeline
nlp.add_pipe("temporal_normalization", last=True)
Processing Text with the Pipeline
doc = nlp(TEXT_RO)
# Display NLP-specific linguistic annotations
console.tokens_table(doc)
print()
Accessing the Parsed Temporal Expressions
# Display information about the identified and normalized dates in the text.
for entity in doc.ents:
time_series = entity._.time_series
if isinstance(time_series, list):
for ts in time_series:
edges = ts.edges
print("Start Edge:")
print(edges.start.serialize("\t"))
print()
print("End Edge:")
print(edges.end.serialize("\t"))
print()
print("Periods:")
for period in ts.periods:
print(period.serialize("\t"))
print()
print("---------------------")
Standalone usage
** Important Note: Even if you choose the standalone approach, the spaCy library will still be loaded on first run, and this process may take a few seconds/tens of seconds.
Importing Modules & Defining Constants
from pathlib import Path
from temporal_normalization import (
close_conn,
console,
extract_temporal_expressions,
start_conn,
TemporalExpression,
)
LANG = "ro"
TEXT_RO = (
"Sec al II-lea a.ch. a fost o perioadă de mari schimbări. "
"În secolul XX, tehnologia a avansat semnificativ. "
"Sec. 21 este adesea asociat cu globalizarea rapidă."
)
Parsing the Content
# Display a warning if the language of the text is not Romanian.
console.lang_warning(TEXT_RO, target_lang=LANG)
root_path = str(Path(__file__).resolve().parent.parent.parent)
java_process, gateway = start_conn(root_path)
expressions: list[TemporalExpression] = extract_temporal_expressions(gateway, TEXT_RO)
close_conn(java_process, gateway)
Accessing the Parsed Temporal Expressions
# Display information about the identified and normalized dates in the text.
for expression in expressions:
for time_series in expression.time_series:
edges = time_series.edges
print("Start Edge:")
print(edges.start.serialize("\t"))
print()
print("End Edge:")
print(edges.end.serialize("\t"))
print()
print("Periods:")
for period in time_series.periods:
print(period.serialize("\t"))
print()
print("---------------------")
Result
First Sentence
Start Edge:
Matched value: Sec al II-lea a.ch.
Matched Type: century
Normalized label: 2nd century BC
DBpedia uri: https://dbpedia.org/resource/2nd_century_BC
End Edge:
Matched value: Sec al II-lea a.ch.
Matched Type: century
Normalized label: 2nd century BC
DBpedia uri: https://dbpedia.org/resource/2nd_century_BC
Periods:
Matched value: Sec al II-lea a.ch.
Matched Type: century
Normalized label: 1st millennium BC
DBpedia uri: https://dbpedia.org/resource/1st_millennium_BC
Matched value: Sec al II-lea a.ch.
Matched Type: century
Normalized label: 2nd century BC
DBpedia uri: https://dbpedia.org/resource/2nd_century_BC
Second Sentence
Start Edge:
Matched value: secolul XX
Matched Type: century
Normalized label: 20th century
DBpedia uri: https://dbpedia.org/resource/20th_century
End Edge:
Matched value: secolul XX
Matched Type: century
Normalized label: 20th century
DBpedia uri: https://dbpedia.org/resource/20th_century
Periods:
Matched value: secolul XX
Matched Type: century
Normalized label: 2nd millennium
DBpedia uri: https://dbpedia.org/resource/2nd_millennium
Matched value: secolul XX
Matched Type: century
Normalized label: 20th century
DBpedia uri: https://dbpedia.org/resource/20th_century
Third Sentence
Start Edge:
Matched value: Sec. 21
Matched Type: century
Normalized label: 21st century
DBpedia uri: https://dbpedia.org/resource/21st_century
End Edge:
Matched value: Sec. 21
Matched Type: century
Normalized label: 21st century
DBpedia uri: https://dbpedia.org/resource/21st_century
Periods:
Matched value: Sec. 21
Matched Type: century
Normalized label: 3rd millennium
DBpedia uri: https://dbpedia.org/resource/3rd_millennium
Matched value: Sec. 21
Matched Type: century
Normalized label: 21st century
DBpedia uri: https://dbpedia.org/resource/21st_century
Publications
ECAI 2021: The Power of Regular Expressions in Recognizing Dates and Epochs (2021)
@inproceedings{9515139,
author={Dorobăț, Ilie Cristian and Posea, Vlad},
booktitle={2021 13th International Conference on Electronics, Computers and Artificial Intelligence (ECAI)},
title={The Power of Regular Expressions in Recognizing Dates and Epochs},
year={2021},
pages={1-3},
doi={10.1109/ECAI52376.2021.9515139}}
Metadata
Release files for temporal-normalization-spacy 2.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| temporal_normalization_spacy-2.3.0.tar.gz | 15.2 MB | Without provenance | Details for temporal_normalization_spacy-2.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| temporal_normalization_spacy-2.3.0-py3-none-any.whl | Python 3 | none | any | Details for temporal_normalization_spacy-2.3.0-py3-none-any.whl |
Total release size: 30.5 MB
Release files / temporal_normalization_spacy-2.3.0.tar.gz
| Download URL | temporal_normalization_spacy-2.3.0.tar.gz |
|---|---|
| Size | 15.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
94b2e88a8c87314df7e12d1be6ea89cce94adac53b755d53b53c7a75a1027ce4
|
|
BLAKE2b-256 checksum How to use checksums |
33ed6e671cedd5433fa5575c68db66f1a3b5fc86b7eae11453d7eb211b7f84f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / temporal_normalization_spacy-2.3.0-py3-none-any.whl
| Download URL | temporal_normalization_spacy-2.3.0-py3-none-any.whl |
|---|---|
| Size | 15.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9acda46fa8a8244e771f829d28938da7cd4d25fba58d6fb316c5f7c4184e77e1
|
|
BLAKE2b-256 checksum How to use checksums |
45b531da120f9087f8056679efe113875a2711765ee6ae4cab8fb96a848ac620
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Security for temporal-normalization-spacy 2.3.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.