python-stdnum branch master updated. 2.2-6-g8a212c7
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
python-stdnum branch master updated. 2.2-6-g8a212c7
- From: Commits of the python-stdnum project <python-stdnum-commits [at] lists.arthurdejong.org>
- To: python-stdnum-commits [at] lists.arthurdejong.org
- Reply-to: python-stdnum-users [at] lists.arthurdejong.org, python-stdnum-commits [at] lists.arthurdejong.org
- Subject: python-stdnum branch master updated. 2.2-6-g8a212c7
- Date: Tue, 11 Aug 2026 16:45:10 +0200 (CEST)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-stdnum".
The branch, master has been updated
via 8a212c7cd1324f326ed30f61b7b2ac43cdf69572 (commit)
from 7662137d48daddf3e6f0e79a69d24197c9761d1c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://arthurdejong.org/git/python-stdnum/commit/?id=8a212c7cd1324f326ed30f61b7b2ac43cdf69572
commit 8a212c7cd1324f326ed30f61b7b2ac43cdf69572
Author: Vincent Gao <gaobing1230@gmail.com>
Date: Tue Jun 16 12:47:18 2026 +0200
Support GS1-128 date AIs with a four-digit year
AI 7250 (DOB, N8 YYYYMMDD) and 7251 (DOB TIME, N12 YYYYMMDDhhmm) use a
four-digit year, but _encode_date() and _decode_date() only handled
two-digit-year formats. Encoding raised "unsupported format: N8" and
decoding raised a bare ValueError: N8 was parsed with '%y%m%d%H' and N12
was mistaken for two YYMMDD dates.
Handle N8 and N12 explicitly in both directions and stop treating N12 as
a pair of dates (only N6[+N6] / N6..12 encode two dates).
Closes https://github.com/arthurdejong/python-stdnum/pull/498
diff --git a/stdnum/gs1_128.py b/stdnum/gs1_128.py
index 001dd58..03cff8a 100644
--- a/stdnum/gs1_128.py
+++ b/stdnum/gs1_128.py
@@ -122,8 +122,15 @@ def _encode_date(fmt: str, value: object) -> str:
# Format date in different formats
if fmt in ('N6', 'N6..12', 'N6[+N6]'):
return value.strftime('%y%m%d')
+ elif fmt == 'N8':
+ # Date with a four-digit year (YYYYMMDD), e.g. AI 7250 (DOB).
+ return value.strftime('%Y%m%d')
elif fmt == 'N10':
return value.strftime('%y%m%d%H%M')
+ elif fmt == 'N12':
+ # Date and time with a four-digit year (YYYYMMDDhhmm), e.g. AI 7251
+ # (DOB TIME).
+ return value.strftime('%Y%m%d%H%M')
elif fmt in ('N6+N..4', 'N6[+N..4]', 'N6[+N4]'):
value = value.strftime('%y%m%d%H%M')
if value.endswith('00'):
@@ -185,7 +192,14 @@ def _decode_decimal(ai: str, fmt: str, value: str) ->
decimal.Decimal | tuple[st
def _decode_date(fmt: str, value: str) -> datetime.date | datetime.datetime |
tuple[datetime.date, datetime.date]:
"""Decode the specified date value given the fmt."""
- if len(value) == 6:
+ if fmt == 'N8':
+ # Date with a four-digit year (YYYYMMDD), e.g. AI 7250 (DOB).
+ return datetime.datetime.strptime(value, '%Y%m%d').date()
+ elif fmt == 'N12':
+ # Date and time with a four-digit year (YYYYMMDDhhmm), e.g. AI 7251
+ # (DOB TIME). This is a single datetime, not two YYMMDD dates.
+ return datetime.datetime.strptime(value, '%Y%m%d%H%M')
+ elif len(value) == 6:
if value[4:] == '00':
# When day == '00', it must be interpreted as last day of month
date = datetime.datetime.strptime(value[:4], '%y%m')
@@ -196,7 +210,7 @@ def _decode_date(fmt: str, value: str) -> datetime.date |
datetime.datetime | tu
return date.date()
else:
return datetime.datetime.strptime(value, '%y%m%d').date()
- elif len(value) == 12 and fmt in ('N12', 'N6..12', 'N6[+N6]'):
+ elif len(value) == 12 and fmt in ('N6..12', 'N6[+N6]'):
return (_decode_date('N6', value[:6]), _decode_date('N6', value[6:]))
# type: ignore[return-value]
else:
# Other lengths are interpreted as variable-length datetime values
diff --git a/tests/test_gs1_128.doctest b/tests/test_gs1_128.doctest
index 7036d27..98172f4 100644
--- a/tests/test_gs1_128.doctest
+++ b/tests/test_gs1_128.doctest
@@ -94,6 +94,10 @@ We generate dates in various formats, depending on the AI.
'(7011)181119'
>>> gs1_128.encode({'7011': datetime.datetime(2018, 11, 19, 12, 45)},
>>> parentheses=True)
'(7011)1811191245'
+>>> gs1_128.encode({'7250': datetime.date(1980, 7, 15)}, parentheses=True) #
four-digit year
+'(7250)19800715'
+>>> gs1_128.encode({'7251': datetime.datetime(1980, 7, 15, 14, 30)},
parentheses=True)
+'(7251)198007151430'
If we try to encode an invalid EAN we will get an error.
@@ -154,6 +158,10 @@ We an decode date files from various formats.
{'7011': datetime.date(2018, 11, 19)}
>>> pprint.pprint(gs1_128.info('(7011)1811191245'))
{'7011': datetime.datetime(2018, 11, 19, 12, 45)}
+>>> pprint.pprint(gs1_128.info('(7250)19800715'))
+{'7250': datetime.date(1980, 7, 15)}
+>>> pprint.pprint(gs1_128.info('(7251)198007151430'))
+{'7251': datetime.datetime(1980, 7, 15, 14, 30)}
While the compact() function can clean up the number somewhat the validate()
-----------------------------------------------------------------------
Summary of changes:
stdnum/gs1_128.py | 18 ++++++++++++++++--
tests/test_gs1_128.doctest | 8 ++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
hooks/post-receive
--
python-stdnum
- python-stdnum branch master updated. 2.2-6-g8a212c7,
Commits of the python-stdnum project