From 78e0090ae4abd0feba831a2efbd55bca442b5a20 Mon Sep 17 00:00:00 2001 From: Karl-Hermann Wieners <karl-hermann.wieners@mpimet.mpg.de> Date: Thu, 20 Feb 2025 17:13:53 +0000 Subject: [PATCH] python: add missing methods to Date/Time/Delta objects * expose attributes (year, month, etc.) * fix binding mismatch and encoding for TimeDelta.sign --- python/mtime/__init__.py | 28 +++++++++- python/mtime/_mtime.py.in | 1 + test/test_python.sh.in | 112 ++++++++++++++++++++------------------ 3 files changed, 87 insertions(+), 54 deletions(-) diff --git a/python/mtime/__init__.py b/python/mtime/__init__.py index be19d2b3..83ac7198 100644 --- a/python/mtime/__init__.py +++ b/python/mtime/__init__.py @@ -59,6 +59,9 @@ class Date(MTime): def __str__(self): return libmtime.dateToString(self._my).decode() + def __getattr__(self, name): + return getattr(self._my.contents, name) + class Time(MTime): def __init__(self, spec): @@ -74,6 +77,9 @@ class Time(MTime): def __str__(self): return libmtime.timeToString(self._my).decode() + def __getattr__(self, name): + return getattr(self._my.contents, name) + class DateTime(MTime): def __init__(self, spec): @@ -113,9 +119,21 @@ class DateTime(MTime): ) return result + def __getattr__(self, name): + try: + return getattr(self._my.contents.date, name) + except AttributeError: + return getattr(self._my.contents.time, name) + def data(self): return self._my + def items(self): + for name, ctype in self._my.contents.date._fields_: + yield (name, getattr(self._my.contents.date, name)) + for name, ctype in self._my.contents.time._fields_: + yield (name, getattr(self._my.contents.time, name)) + @property def date(self): return Date( @@ -162,9 +180,17 @@ class TimeDelta(MTime): ) return result.contents.quotient + def __getattr__(self, name): + return getattr(self._my.contents, name) + def data(self): return self._my def items(self): for name, ctype in self._my.contents._fields_: - yield (name, self._my.contents.__getattribute__(name)) + if not name.startswith("_"): + yield (name, getattr(self, name)) + + @property + def sign(self): + return self._my.contents.sign.decode() diff --git a/python/mtime/_mtime.py.in b/python/mtime/_mtime.py.in index 8127560c..f6a99523 100644 --- a/python/mtime/_mtime.py.in +++ b/python/mtime/_mtime.py.in @@ -461,6 +461,7 @@ max_timedelta_str_len = c_int(32).value class _timedelta(Structure): _fields_ = [ + ("_flag_std_form", c_int), ("sign", c_char), ("year", c_long), ("month", c_int), diff --git a/test/test_python.sh.in b/test/test_python.sh.in index 25917b4d..264e18c4 100644 --- a/test/test_python.sh.in +++ b/test/test_python.sh.in @@ -21,52 +21,72 @@ exec @PYTHON@ "$0" ":""" import mtime -# Test initialization and time delta arithmetics -print("-" * 80) -initial_date = mtime.DateTime("1850-01-01") +# Setup, testing initialization and time delta arithmetics +initial_date = mtime.DateTime("1850-01-23T12:34:56.789") start_date = initial_date + mtime.TimeDelta("P1Y") -print(initial_date) -print(start_date) +timestep = mtime.TimeDelta("PT15M") +next_date = start_date + mtime.TimeDelta("P1Y") +after_date = next_date + mtime.TimeDelta("P1Y") -# Test before/after tests on datetime objects print("-" * 80) -test_result = start_date == start_date -print(str(start_date) + " == " + str(start_date) + ": " + str(test_result)) -assert test_result - -test_result = start_date > initial_date -print(str(start_date) + " > " + str(initial_date) + ": " + str(test_result)) -assert test_result +tests = "" -test_result = start_date == initial_date -print(str(start_date) + " == " + str(initial_date) + ": " + str(test_result)) -assert not test_result +# Test string conversion and show setup values +tests += """ +str(initial_date) == "1850-01-23T12:34:56.789" +str(start_date) == "1851-01-23T12:34:56.789" +str(timestep) == "PT15M" +str(next_date) == "1852-01-23T12:34:56.789" +str(after_date) == "1853-01-23T12:34:56.789" +""" -test_result = start_date < initial_date -print(str(start_date) + " < " + str(initial_date) + ": " + str(test_result)) -assert not test_result +# Test before/after tests on datetime objects +tests += """ +start_date == start_date +start_date > initial_date +not (start_date == initial_date) +not (start_date < initial_date) +""" # Test division by delta -print("-" * 80) -timestep = mtime.TimeDelta("PT15M") -test_result = (start_date, initial_date) // timestep -print( - "({0}, {1})//{2}: {3}".format( - start_date, - initial_date, - timestep, - test_result, - ) -) -assert test_result == 35040 - -next_date = start_date + mtime.TimeDelta("P1Y") -after_date = next_date + mtime.TimeDelta("P1Y") -test_result = (after_date, next_date) // timestep -print( - "({0}, {1})//{2}: {3}".format(after_date, next_date, timestep, test_result) -) -assert test_result == 35136 +tests += """ +(start_date, initial_date)//timestep == 35040 +(after_date, next_date)//timestep == 35136 +""" + +# Test attribute selection, also for date and time only parts +tests += """ +str(start_date.date) == "1851-01-23" +str(start_date.time) == "12:34:56.789" +start_date.year == 1851 +start_date.month == 1 +start_date.day == 23 +start_date.hour == 12 +start_date.minute == 34 +start_date.second == 56 +start_date.ms == 789 +start_date.date.year == 1851 +start_date.date.month == 1 +start_date.date.day == 23 +start_date.time.hour == 12 +start_date.time.minute == 34 +start_date.time.second == 56 +start_date.time.ms == 789 +timestep.sign == "+" +timestep.year == 0 +timestep.month == 0 +timestep.day == 0 +timestep.hour == 0 +timestep.minute == 15 +timestep.second == 0 +timestep.ms == 0 +""" + +test_result = False +for test in filter(None, tests.split("\n")): + test_result = eval(test) + print("{0}: {1}".format(test, test_result)) + assert test_result # Test re-initializing of calendar, showing Feb 28th and successing days @@ -124,17 +144,3 @@ assert next_day == mtime.DateTime("1852-02-30") next_day += mtime.TimeDelta("P1D") print(next_day) assert next_day == mtime.DateTime("1852-03-01") - -# Test selection and string conversion for date and time only parts -print("-" * 80) -test_result = str(start_date) -print(test_result) -assert test_result == "1851-01-01T00:00:00.000" - -test_result = str(start_date.date) -print(test_result) -assert test_result == "1851-01-01" - -test_result = str(start_date.time) -print(test_result) -assert test_result == "00:00:00.000" -- GitLab