[GRASS-SVN] r71573 - in grass/trunk/lib/python/temporal: . testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Oct 21 08:01:49 PDT 2017


Author: huhabla
Date: 2017-10-21 08:01:49 -0700 (Sat, 21 Oct 2017)
New Revision: 71573

Modified:
   grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
   grass/trunk/lib/python/temporal/core.py
   grass/trunk/lib/python/temporal/datetime_math.py
   grass/trunk/lib/python/temporal/space_time_datasets.py
   grass/trunk/lib/python/temporal/temporal_algebra.py
   grass/trunk/lib/python/temporal/testsuite/test_doctests.py
Log:
temporal framework: Better datetime string parsing. Parsing of datetime strings is now done in a single place.


Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -26,7 +26,7 @@
 from .spatio_temporal_relationships import count_temporal_topology_relationships, \
     print_spatio_temporal_topology_relationships, SpatioTemporalTopologyBuilder, \
     create_temporal_relation_sql_where_statement
-from .datetime_math import increment_datetime_by_string
+from .datetime_math import increment_datetime_by_string, string_to_datetime
 
 ###############################################################################
 
@@ -2377,13 +2377,9 @@
                     tstring = row[0]
                     # Convert the unicode string into the datetime format
                     if self.is_time_absolute():
-                        if tstring.find(":") > 0:
-                            time_format = "%Y-%m-%d %H:%M:%S"
-                        else:
-                            time_format = "%Y-%m-%d"
-
-                        max_start_time = datetime.strptime(
-                            tstring, time_format)
+                        max_start_time = string_to_datetime(tstring)
+                        if max_start_time is None:
+                            max_start_time = end_time
                     else:
                         max_start_time = row[0]
                 else:

Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/core.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -55,6 +55,7 @@
     pass
 
 import atexit
+from datetime import datetime
 
 ###############################################################################
 
@@ -1207,12 +1208,15 @@
                     elif isinstance(args[count], float):
                         statement = "%s%f%s" % (statement[0:pos], args[count],
                                                 statement[pos + 1:])
+                    elif isinstance(args[count], datetime):
+                        statement = "%s\'%s\'%s" % (statement[0:pos], str(args[count]),
+                                                statement[pos + 1:])
                     else:
                         # Default is a string, this works for datetime
                         # objects too
                         statement = "%s\'%s\'%s" % (statement[0:pos],
                                                     str(args[count]),
-                                                    statement[pos + 1:])
+                                                    str(statement[pos + 1:]))
                     count += 1
 
                 return statement

Modified: grass/trunk/lib/python/temporal/datetime_math.py
===================================================================
--- grass/trunk/lib/python/temporal/datetime_math.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/datetime_math.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -704,23 +704,65 @@
 ###############################################################################
 
 
-def check_datetime_string(time_string):
-    """Check if  a string can be converted into a datetime object
+def check_datetime_string(time_string, use_dateutil=True):
+    """Check if  a string can be converted into a datetime object and return the object
 
-        Supported ISO string formats are:
+        In case datutil is not installed the supported ISO string formats are:
 
         - YYYY-mm-dd
         - YYYY-mm-dd HH:MM:SS
+        - YYYY-mm-ddTHH:MM:SS
+        - YYYY-mm-dd HH:MM:SS.s
+        - YYYY-mm-ddTHH:MM:SS.s
 
         Time zones are not supported
 
+        If dateutil is installed, all string formats of the dateutil module
+        are supported, as well as time zones
+        Time zones are not supported
+
         :param time_string: The time string to be checked for conversion
+        :param use_dateutil: Use dateutil if available for datetime string parsing
         :return: datetime: object or an error message string in case of an error
+
+        >>> s = "2000-01-01"
+        >>> check_datetime_string(s)
+        datetime.datetime(2000, 1, 1, 0, 0)
+        >>> s = "2000-01-01T10:00:00"
+        >>> check_datetime_string(s)
+        datetime.datetime(2000, 1, 1, 10, 0)
+        >>> s = "2000-01-01 10:00:00"
+        >>> check_datetime_string(s)
+        datetime.datetime(2000, 1, 1, 10, 0)
+        >>> s = "2000-01-01T10:00:00.000001"
+        >>> check_datetime_string(s)
+        datetime.datetime(2000, 1, 1, 10, 0, 0, 1)
+        >>> s = "2000-01-01 10:00:00.000001"
+        >>> check_datetime_string(s)
+        datetime.datetime(2000, 1, 1, 10, 0, 0, 1)
+
+        # using native implementation, ignoring dateutil
+        >>> s = "2000-01-01"
+        >>> check_datetime_string(s, False)
+        datetime.datetime(2000, 1, 1, 0, 0)
+        >>> s = "2000-01-01T10:00:00"
+        >>> check_datetime_string(s, False)
+        datetime.datetime(2000, 1, 1, 10, 0)
+        >>> s = "2000-01-01 10:00:00"
+        >>> check_datetime_string(s, False)
+        datetime.datetime(2000, 1, 1, 10, 0)
+        >>> s = "2000-01-01T10:00:00.000001"
+        >>> check_datetime_string(s, False)
+        datetime.datetime(2000, 1, 1, 10, 0, 0, 1)
+        >>> s = "2000-01-01 10:00:00.000001"
+        >>> check_datetime_string(s, False)
+        datetime.datetime(2000, 1, 1, 10, 0, 0, 1)
+
     """
 
     global has_dateutil
 
-    if has_dateutil:
+    if has_dateutil and use_dateutil is True:
         # First check if there is only a single number, which specifies
         # relative time. dateutil will interprete a single number as a valid
         # time string, so we have to catch this case beforehand
@@ -737,15 +779,25 @@
         return time_object
 
     # BC is not supported
-    if time_string.find("bc") > 0:
+    if "bc" in time_string > 0:
         return _("Dates Before Christ (BC) are not supported")
 
     # BC is not supported
-    if time_string.find("+") > 0:
+    if "+" in time_string:
         return _("Time zones are not supported")
 
-    if time_string.find(":") > 0:
-        time_format = "%Y-%m-%d %H:%M:%S"
+    if ":" in time_string or "T" in time_string:
+        # Check for microseconds
+        if "." in time_string:
+            if "T" in time_string:
+                time_format = "%Y-%m-%dT%H:%M:%S.%f"
+            else:
+                time_format = "%Y-%m-%d %H:%M:%S.%f"
+        else:
+            if "T" in time_string:
+                time_format = "%Y-%m-%dT%H:%M:%S"
+            else:
+                time_format = "%Y-%m-%d %H:%M:%S"
     else:
         time_format = "%Y-%m-%d"
 
@@ -764,8 +816,12 @@
 
         - YYYY-mm-dd
         - YYYY-mm-dd HH:MM:SS
-        - Time zones are not supported
+        - YYYY-mm-ddTHH:MM:SS
+        - YYYY-mm-dd HH:MM:SS.s
+        - YYYY-mm-ddTHH:MM:SS.s
 
+        Time zones are not supported
+
         If dateutil is installed, all string formats of the dateutil module
         are supported, as well as time zones
 

Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -119,7 +119,7 @@
             >>> rmap.get_temporal_extent_as_tuple()
             (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
             >>> rmap.get_name()
-            u'strds_map_test_case'
+            'strds_map_test_case'
             >>> rmap.get_mapset() == mapset
             True
             >>> rmap.get_temporal_type()
@@ -452,7 +452,7 @@
             >>> r3map.get_temporal_extent_as_tuple()
             (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
             >>> r3map.get_name()
-            u'str3ds_map_test_case'
+            'str3ds_map_test_case'
             >>> r3map.get_mapset() == mapset
             True
             >>> r3map.get_temporal_type()
@@ -797,7 +797,7 @@
             >>> vmap.get_temporal_extent_as_tuple()
             (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
             >>> vmap.get_name()
-            u'stvds_map_test_case'
+            'stvds_map_test_case'
             >>> vmap.get_mapset() == mapset
             True
             >>> vmap.get_temporal_type()

Modified: grass/trunk/lib/python/temporal/temporal_algebra.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_algebra.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/temporal_algebra.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -463,7 +463,7 @@
 from .open_stds import open_new_stds, open_old_stds
 from .temporal_operator import TemporalOperatorParser
 from spatio_temporal_relationships import SpatioTemporalTopologyBuilder
-from .datetime_math import time_delta_to_relative_time
+from .datetime_math import time_delta_to_relative_time, string_to_datetime
 from abstract_space_time_dataset import AbstractSpaceTimeDataset
 
 ##############################################################################
@@ -1965,18 +1965,11 @@
             # Get value for function name from dictionary.
             tfuncval = tfuncdict[tfunc]
             # Check if value has to be transferred to datetime object for comparison.
-            if tfunc in ["START_DATE", "END_DATE"]:
-                timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d')
+            if tfunc in ["START_DATE", "END_DATE", "START_TIME", "END_TIME",
+                         "START_DATETIME", "END_DATETIME"]:
+                timeobj = string_to_datetime(value.replace("\"",""))
                 value = timeobj.date()
                 boolname = self.eval_datetime_str(tfuncval, comp_op, value)
-            elif tfunc in ["START_TIME", "END_TIME"]:
-                timeobj = datetime.strptime(value.replace("\"",""), '%H:%M:%S')
-                value = timeobj.time()
-                boolname = self.eval_datetime_str(tfuncval, comp_op, value)
-            elif tfunc in ["START_DATETIME", "END_DATETIME"]:
-                timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d %H:%M:%S')
-                value = timeobj
-                boolname = self.eval_datetime_str(tfuncval, comp_op, value)
             else:
                 boolname = eval(str(tfuncval) + comp_op + str(value))
             # Add conditional boolean value to the map.

Modified: grass/trunk/lib/python/temporal/testsuite/test_doctests.py
===================================================================
--- grass/trunk/lib/python/temporal/testsuite/test_doctests.py	2017-10-21 13:34:13 UTC (rev 71572)
+++ grass/trunk/lib/python/temporal/testsuite/test_doctests.py	2017-10-21 15:01:49 UTC (rev 71573)
@@ -24,11 +24,10 @@
     tests.addTests(doctest.DocTestSuite(grass.temporal.abstract_map_dataset))
     tests.addTests(doctest.DocTestSuite(grass.temporal.abstract_space_time_dataset))
     tests.addTests(doctest.DocTestSuite(grass.temporal.base))
-    # Unexpected error here
     tests.addTests(doctest.DocTestSuite(grass.temporal.core))
     tests.addTests(doctest.DocTestSuite(grass.temporal.datetime_math))
     # Unexpected error here
-    ##tests.addTests(doctest.DocTestSuite(grass.temporal.list_stds))
+    #tests.addTests(doctest.DocTestSuite(grass.temporal.list_stds))
     tests.addTests(doctest.DocTestSuite(grass.temporal.metadata))
     tests.addTests(doctest.DocTestSuite(grass.temporal.register))
     tests.addTests(doctest.DocTestSuite(grass.temporal.space_time_datasets))



More information about the grass-commit mailing list