浏览代码

Read support for timestamps set with *.timestamp modules implemented.

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@58078 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 11 年之前
父节点
当前提交
376a7d8604
共有 2 个文件被更改,包括 363 次插入38 次删除
  1. 116 20
      lib/python/temporal/abstract_map_dataset.py
  2. 247 18
      lib/python/temporal/space_time_datasets.py

+ 116 - 20
lib/python/temporal/abstract_map_dataset.py

@@ -14,6 +14,9 @@ for details.
 """
 """
 from abstract_dataset import *
 from abstract_dataset import *
 from datetime_math import *
 from datetime_math import *
+import grass.lib.date as libdate
+import grass.lib.gis as libgis
+import ctypes
 
 
 
 
 class AbstractMapDataset(AbstractDataset):
 class AbstractMapDataset(AbstractDataset):
@@ -89,6 +92,7 @@ class AbstractMapDataset(AbstractDataset):
         raise ImplementationError(
         raise ImplementationError(
             "This method must be implemented in the subclasses")
             "This method must be implemented in the subclasses")
 
 
+
     @abstractmethod
     @abstractmethod
     def has_grass_timestamp(self):
     def has_grass_timestamp(self):
         """!Check if a grass file based time stamp exists for this map.
         """!Check if a grass file based time stamp exists for this map.
@@ -103,6 +107,91 @@ class AbstractMapDataset(AbstractDataset):
         """
         """
 
 
     @abstractmethod
     @abstractmethod
+    def read_timestamp_from_grass(self):
+        """!Read the timestamp of this map from the map metadata
+           in the grass file system based spatial database and
+           set the internal time stamp that should be insert/updated
+           in the temporal database.
+        """
+
+    def _set_timestamp_from_grass(self, ts):
+        """!Set the timestamp of this map from the map metadata
+           in the grass file system based spatial database and
+           set the internal time stamp that should be insert/updated
+           in the temporal database.
+           
+           @param ts The timetsamp to be set, is of type libgis.TimeStamp()
+        """
+        
+        if not self.has_grass_timestamp():
+            return False
+
+        dt1 = libgis.DateTime()
+        dt2 = libgis.DateTime()
+        count = ctypes.c_int()
+
+        libgis.G_get_timestamps(ctypes.byref(ts), 
+                                ctypes.byref(dt1), 
+                                ctypes.byref(dt2), 
+                                ctypes.byref(count))
+                                 
+        
+        if dt1.mode == libdate.DATETIME_ABSOLUTE:
+            pdt1 = None
+            pdt2 = None
+            if count >= 1:
+                pdt1 = datetime(int(dt1.year), int(dt1.month), int(dt1.day), 
+                                int(dt1.hour), int(dt1.minute), 
+                                int(dt1.second))
+            if count == 2:
+                pdt2 = datetime(int(dt2.year), int(dt2.month), int(dt2.day), 
+                                int(dt2.hour), int(dt2.minute), 
+                                int(dt2.second))
+
+            # ATTENTION: We ignore the time zone
+            # TODO: Write time zone support
+            self.set_absolute_time(pdt1, pdt2, None)
+        else:
+            unit = None
+            start = None
+            end = None
+            if count >= 1:
+                if dt1.year > 0:
+                    unit = "years"
+                    start = dt1.year
+                elif dt1.month > 0:
+                    unit = "months"
+                    start = dt1.month
+                elif dt1.day > 0:
+                    unit = "days"
+                    start = dt1.day
+                elif dt1.hour > 0:
+                    unit = "hours"
+                    start = dt1.hour
+                elif dt1.minute > 0:
+                    unit = "minutess"
+                    start = dt1.minutes
+                elif dt1.seconds > 0:
+                    unit = "seconds"
+                    start = dt1.seconds
+            if count == 2:
+                if dt2.year > 0:
+                    end = dt2.year
+                elif dt2.month > 0:
+                    end = dt2.month
+                elif dt2.day > 0:
+                    end = dt2.day
+                elif dt2.hour > 0:
+                    end = dt2.hour
+                elif dt2.minute > 0:
+                    end = dt2.minutes
+                elif dt2.seconds > 0:
+                    end = dt2.seconds
+            self.set_relative_time(start, end, unit)
+ 
+        return True
+
+    @abstractmethod
     def remove_timestamp_from_grass(self):
     def remove_timestamp_from_grass(self):
         """!Remove the timestamp from the grass file
         """!Remove the timestamp from the grass file
            system based spatial database
            system based spatial database
@@ -344,42 +433,50 @@ class AbstractMapDataset(AbstractDataset):
            @param end_time a datetime object specifying the end time of the
            @param end_time a datetime object specifying the end time of the
                            map, None in case or time instance
                            map, None in case or time instance
            @param timezone Thee timezone of the map (not used)
            @param timezone Thee timezone of the map (not used)
+           
+           @return True for success and False otherwise
         """
         """
         if start_time and not isinstance(start_time, datetime):
         if start_time and not isinstance(start_time, datetime):
             if self.get_layer() is not None:
             if self.get_layer() is not None:
-                core.fatal(_("Start time must be of type datetime for %(type)s"
+                core.error(_("Start time must be of type datetime for %(type)s"
                              " map <%(id)s> with layer: %(l)s") % {
                              " map <%(id)s> with layer: %(l)s") % {
                              'type': self.get_type(), 'id': self.get_map_id(),
                              'type': self.get_type(), 'id': self.get_map_id(),
                              'l': self.get_layer()})
                              'l': self.get_layer()})
+                return False
             else:
             else:
-                core.fatal(_("Start time must be of type datetime for "
+                core.error(_("Start time must be of type datetime for "
                              "%(type)s map <%(id)s>") % {
                              "%(type)s map <%(id)s>") % {
                              'type': self.get_type(), 'id': self.get_map_id()})
                              'type': self.get_type(), 'id': self.get_map_id()})
+                return False
 
 
         if end_time and not isinstance(end_time, datetime):
         if end_time and not isinstance(end_time, datetime):
             if self.get_layer():
             if self.get_layer():
-                core.fatal(_("End time must be of type datetime for %(type)s "
+                core.error(_("End time must be of type datetime for %(type)s "
                              "map <%(id)s> with layer: %(l)s") % {
                              "map <%(id)s> with layer: %(l)s") % {
                              'type': self.get_type(), 'id': self.get_map_id(),
                              'type': self.get_type(), 'id': self.get_map_id(),
                              'l': self.get_layer()})
                              'l': self.get_layer()})
+                return False
             else:
             else:
-                core.fatal(_("End time must be of type datetime for "
+                core.error(_("End time must be of type datetime for "
                              "%(type)s map <%(id)s>") % {
                              "%(type)s map <%(id)s>") % {
                              'type': self.get_type(), 'id': self.get_map_id()})
                              'type': self.get_type(), 'id': self.get_map_id()})
+                return False
 
 
         if start_time is not None and end_time is not None:
         if start_time is not None and end_time is not None:
             if start_time > end_time:
             if start_time > end_time:
                 if self.get_layer():
                 if self.get_layer():
-                    core.fatal(_("End time must be greater than start time for"
+                    core.error(_("End time must be greater than start time for"
                                  " %(type)s map <%(id)s> with layer: %(l)s") % {
                                  " %(type)s map <%(id)s> with layer: %(l)s") % {
                                  'type': self.get_type(),
                                  'type': self.get_type(),
                                  'id': self.get_map_id(),
                                  'id': self.get_map_id(),
                                  'l': self.get_layer()})
                                  'l': self.get_layer()})
+                    return False
                 else:
                 else:
-                    core.fatal(_("End time must be greater than start time "
+                    core.error(_("End time must be greater than start time "
                                  "for %(type)s map <%(id)s>") % {
                                  "for %(type)s map <%(id)s>") % {
                                  'type': self.get_type(),
                                  'type': self.get_type(),
                                  'id': self.get_map_id()})
                                  'id': self.get_map_id()})
+                    return False
             else:
             else:
                 # Do not create an interval in case start and end time are
                 # Do not create an interval in case start and end time are
                 # equal
                 # equal
@@ -417,16 +514,16 @@ class AbstractMapDataset(AbstractDataset):
                          " The mapset of the dataset does not match the current mapset")%\
                          " The mapset of the dataset does not match the current mapset")%\
                          {"ds":self.get_id(), "type":self.get_type()})
                          {"ds":self.get_id(), "type":self.get_type()})
             
             
-        dbif, connected = init_dbif(dbif)
 
 
-        self.set_absolute_time(start_time, end_time, timezone)
-        self.absolute_time.update_all(dbif)
-        self.base.update(dbif)
-
-        if connected:
-            dbif.close()
+        if self.set_absolute_time(start_time, end_time, timezone):
+            dbif, connected = init_dbif(dbif)
+            self.absolute_time.update_all(dbif)
+            self.base.update(dbif)
 
 
-        self.write_timestamp_to_grass()
+            if connected:
+                dbif.close()
+    
+            self.write_timestamp_to_grass()
 
 
     def set_relative_time(self, start_time, end_time, unit):
     def set_relative_time(self, start_time, end_time, unit):
         """!Set the relative time interval
         """!Set the relative time interval
@@ -507,16 +604,15 @@ class AbstractMapDataset(AbstractDataset):
                          " The mapset of the dataset does not match the current mapset")%\
                          " The mapset of the dataset does not match the current mapset")%\
                          {"ds":self.get_id(), "type":self.get_type()})
                          {"ds":self.get_id(), "type":self.get_type()})
 
 
-        dbif, connected = init_dbif(dbif)
-
         if self.set_relative_time(start_time, end_time, unit):
         if self.set_relative_time(start_time, end_time, unit):
+            dbif, connected = init_dbif(dbif)
             self.relative_time.update_all(dbif)
             self.relative_time.update_all(dbif)
             self.base.update(dbif)
             self.base.update(dbif)
 
 
-        if connected:
-            dbif.close()
-
-        self.write_timestamp_to_grass()
+            if connected:
+                dbif.close()
+    
+            self.write_timestamp_to_grass()
 
 
     def set_temporal_extent(self, extent):
     def set_temporal_extent(self, extent):
         """!Convenient method to set the temporal extent from a temporal extent object
         """!Convenient method to set the temporal extent from a temporal extent object

+ 247 - 18
lib/python/temporal/space_time_datasets.py

@@ -9,15 +9,6 @@ This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 License (>=v2). Read the file COPYING that comes with GRASS
 for details.
 for details.
 
 
-
->>> import grass.script as grass
-
->>> grass.run_command("r3.mapcalc", overwrite=True, expression="str3ds_map_test_case = 1")
-0
->>> grass.run_command("v.random", overwrite=True, output="stvds_map_test_case",
-... n=100, zmin=0, zmax=100, flags="z", column="elevation")
-0
-
 @author Soeren Gebbert
 @author Soeren Gebbert
 """
 """
 import getpass
 import getpass
@@ -52,15 +43,19 @@ class RasterDataset(AbstractMapDataset):
         >>> grass.run_command("r.mapcalc", overwrite=True,
         >>> grass.run_command("r.mapcalc", overwrite=True,
         ... expression="strds_map_test_case = 1")
         ... expression="strds_map_test_case = 1")
         0
         0
+        >>> grass.run_command("r.timestamp", map="strds_map_test_case", 
+        ...                   date="15 jan 1999")
+        0
         >>> mapset = get_current_mapset()
         >>> mapset = get_current_mapset()
         >>> name = "strds_map_test_case"
         >>> name = "strds_map_test_case"
         >>> identifier = "%s@%s" % (name, mapset)
         >>> identifier = "%s@%s" % (name, mapset)
         >>> rmap = RasterDataset(identifier)
         >>> rmap = RasterDataset(identifier)
-        >>> rmap.set_absolute_time(start_time=datetime(2001,1,1),
-        ...                        end_time=datetime(2012,1,1))
-        True
         >>> rmap.map_exists()
         >>> rmap.map_exists()
         True
         True
+        >>> rmap.read_timestamp_from_grass()
+        True
+        >>> rmap.get_temporal_extent_as_tuple()
+        (datetime.datetime(1999, 1, 15, 0, 0), None)
         >>> rmap.load()
         >>> rmap.load()
         >>> rmap.spatial_extent.print_info()
         >>> rmap.spatial_extent.print_info()
          +-------------------- Spatial extent ----------------------------------------+
          +-------------------- Spatial extent ----------------------------------------+
@@ -72,8 +67,8 @@ class RasterDataset(AbstractMapDataset):
          | Bottom:..................... 0.0
          | Bottom:..................... 0.0
         >>> rmap.absolute_time.print_info()
         >>> rmap.absolute_time.print_info()
          +-------------------- Absolute time -----------------------------------------+
          +-------------------- Absolute time -----------------------------------------+
-         | Start time:................. 2001-01-01 00:00:00
-         | End time:................... 2012-01-01 00:00:00
+         | Start time:................. 1999-01-15 00:00:00
+         | End time:................... None
         >>> rmap.metadata.print_info()
         >>> rmap.metadata.print_info()
          +-------------------- Metadata information ----------------------------------+
          +-------------------- Metadata information ----------------------------------+
          | Datatype:................... CELL
          | Datatype:................... CELL
@@ -95,6 +90,9 @@ class RasterDataset(AbstractMapDataset):
         >>> rmap.get_type()
         >>> rmap.get_type()
         'raster'
         'raster'
         >>> rmap.get_stds_register()
         >>> rmap.get_stds_register()
+        >>> rmap.set_absolute_time(start_time=datetime(2001,1,1),
+        ...                        end_time=datetime(2012,1,1))
+        True
         >>> rmap.get_absolute_time()
         >>> rmap.get_absolute_time()
         (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
         (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
         >>> rmap.get_temporal_extent_as_tuple()
         >>> rmap.get_temporal_extent_as_tuple()
@@ -211,11 +209,32 @@ class RasterDataset(AbstractMapDataset):
     def has_grass_timestamp(self):
     def has_grass_timestamp(self):
         """!Check if a grass file bsased time stamp exists for this map.
         """!Check if a grass file bsased time stamp exists for this map.
         """
         """
-        if G_has_raster_timestamp(self.get_name(), self.get_mapset()):
+        if libgis.G_has_raster_timestamp(self.get_name(), self.get_mapset()):
             return True
             return True
         else:
         else:
             return False
             return False
 
 
+    def read_timestamp_from_grass(self):
+        """!Read the timestamp of this map from the map metadata
+           in the grass file system based spatial database and
+           set the internal time stamp that should be insert/updated
+           in the temporal database.
+        """
+
+        if not self.has_grass_timestamp():
+            return False
+
+        ts = libgis.TimeStamp()
+        check = libgis.G_read_raster_timestamp(self.get_name(), self.get_mapset(),
+                                               byref(ts))
+
+        if check < 1:
+            core.error(_("Unable to read timestamp file "
+                         "for raster map <%s>" % (self.get_map_id())))
+            return False
+        
+        return self._set_timestamp_from_grass(ts)
+
     def write_timestamp_to_grass(self):
     def write_timestamp_to_grass(self):
         """!Write the timestamp of this map into the map metadata in
         """!Write the timestamp of this map into the map metadata in
            the grass file system based spatial database.
            the grass file system based spatial database.
@@ -376,7 +395,92 @@ class Raster3DDataset(AbstractMapDataset):
     """!Raster3d dataset class
     """!Raster3d dataset class
 
 
        This class provides functions to select, update, insert or delete raster3d
        This class provides functions to select, update, insert or delete raster3d
-       map information and valid time stamps into the SQL temporal database.
+       map information and valid time stamps into the SQL temporal database.       
+       
+       Usage:
+
+        @code
+
+        >>> import grass.script as grass
+        >>> init()
+        >>> grass.use_temp_region()
+        >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
+        ... t=100.0, b=0.0, res=10.0)
+        0
+        >>> grass.run_command("r3.mapcalc", overwrite=True, 
+        ...                   expression="str3ds_map_test_case = 1")
+        0
+        >>> grass.run_command("r3.timestamp", map="str3ds_map_test_case", 
+        ...                   date="15 jan 1999")
+        0
+        >>> mapset = get_current_mapset()
+        >>> name = "str3ds_map_test_case"
+        >>> identifier = "%s@%s" % (name, mapset)
+        >>> r3map = Raster3DDataset(identifier)
+        >>> r3map.map_exists()
+        True
+        >>> r3map.read_timestamp_from_grass()
+        True
+        >>> r3map.get_temporal_extent_as_tuple()
+        (datetime.datetime(1999, 1, 15, 0, 0), None)
+        >>> r3map.load()
+        >>> r3map.spatial_extent.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 0.0
+         | East:.. .................... 120.0
+         | West:....................... 0.0
+         | Top:........................ 100.0
+         | Bottom:..................... 0.0
+        >>> r3map.absolute_time.print_info()
+         +-------------------- Absolute time -----------------------------------------+
+         | Start time:................. 1999-01-15 00:00:00
+         | End time:................... None
+        >>> r3map.metadata.print_info()
+         +-------------------- Metadata information ----------------------------------+
+         | Datatype:................... DCELL
+         | Number of columns:.......... 8
+         | Number of rows:............. 12
+         | Number of cells:............ 960
+         | North-South resolution:..... 10.0
+         | East-west resolution:....... 10.0
+         | Minimum value:.............. 1.0
+         | Maximum value:.............. 1.0
+         | Number of depths:........... 10
+         | Top-Bottom resolution:...... 10.0
+         | STR3DS register table ...... None
+
+        >>> newmap = r3map.get_new_instance("new@PERMANENT")
+        >>> isinstance(newmap, Raster3DDataset)
+        True
+        >>> newstr3ds = r3map.get_new_stds_instance("new@PERMANENT")
+        >>> isinstance(newstr3ds, SpaceTimeRaster3DDataset)
+        True
+        >>> r3map.get_type()
+        'raster3d'
+        >>> r3map.get_stds_register()
+        >>> r3map.set_absolute_time(start_time=datetime(2001,1,1),
+        ...                        end_time=datetime(2012,1,1))
+        True
+        >>> r3map.get_absolute_time()
+        (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
+        >>> r3map.get_temporal_extent_as_tuple()
+        (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
+        >>> r3map.get_name()
+        'str3ds_map_test_case'
+        >>> r3map.get_mapset() == mapset
+        True
+        >>> r3map.get_temporal_type()
+        'absolute'
+        >>> r3map.get_spatial_extent_as_tuple()
+        (80.0, 0.0, 120.0, 0.0, 100.0, 0.0)
+        >>> r3map.is_time_absolute()
+        True
+        >>> r3map.is_time_relative()
+        False
+        >>> grass.run_command("g.remove", rast3d=name)
+        0
+        >>> grass.del_temp_region()
     """
     """
     def __init__(self, ident):
     def __init__(self, ident):
         AbstractMapDataset.__init__(self)
         AbstractMapDataset.__init__(self)
@@ -486,11 +590,33 @@ class Raster3DDataset(AbstractMapDataset):
     def has_grass_timestamp(self):
     def has_grass_timestamp(self):
         """!Check if a grass file bsased time stamp exists for this map.
         """!Check if a grass file bsased time stamp exists for this map.
         """
         """
-        if G_has_raster3d_timestamp(self.get_name(), self.get_mapset()):
+        if libgis.G_has_raster3d_timestamp(self.get_name(), self.get_mapset()):
             return True
             return True
         else:
         else:
             return False
             return False
 
 
+
+    def read_timestamp_from_grass(self):
+        """!Read the timestamp of this map from the map metadata
+           in the grass file system based spatial database and
+           set the internal time stamp that should be insert/updated
+           in the temporal database.
+        """
+
+        if not self.has_grass_timestamp():
+            return False
+
+        ts = libgis.TimeStamp()
+        check = libgis.G_read_raster3d_timestamp(self.get_name(), self.get_mapset(),
+                                               byref(ts))
+
+        if check < 1:
+            core.error(_("Unable to read timestamp file "
+                         "for 3D raster map <%s>" % (self.get_map_id())))
+            return False
+        
+        return self._set_timestamp_from_grass(ts)
+        
     def write_timestamp_to_grass(self):
     def write_timestamp_to_grass(self):
         """!Write the timestamp of this map into the map metadata
         """!Write the timestamp of this map into the map metadata
         in the grass file system based spatial database.
         in the grass file system based spatial database.
@@ -654,6 +780,85 @@ class VectorDataset(AbstractMapDataset):
 
 
        This class provides functions to select, update, insert or delete vector
        This class provides functions to select, update, insert or delete vector
        map information and valid time stamps into the SQL temporal database.
        map information and valid time stamps into the SQL temporal database.
+       
+       Usage:
+
+        @code
+
+        >>> import grass.script as grass
+        >>> init()
+        >>> grass.use_temp_region()
+        >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
+        ... t=1.0, b=0.0, res=10.0)
+        0
+        >>> grass.run_command("v.random", overwrite=True, output="stvds_map_test_case",
+        ... n=100, zmin=0, zmax=100, flags="z", column="elevation")
+        0
+        >>> grass.run_command("v.timestamp", map="stvds_map_test_case", 
+        ...                   date="15 jan 1999")
+        0
+        >>> mapset = get_current_mapset()
+        >>> name = "stvds_map_test_case"
+        >>> identifier = "%s@%s" % (name, mapset)
+        >>> vmap = VectorDataset(identifier)
+        >>> vmap.map_exists()
+        True
+        >>> vmap.read_timestamp_from_grass()
+        True
+        >>> vmap.get_temporal_extent_as_tuple()
+        (datetime.datetime(1999, 1, 15, 0, 0), None)
+        >>> vmap.load()
+        >>> vmap.absolute_time.print_info()
+         +-------------------- Absolute time -----------------------------------------+
+         | Start time:................. 1999-01-15 00:00:00
+         | End time:................... None
+        >>> vmap.metadata.print_info()
+         +-------------------- Metadata information ----------------------------------+
+         | STVDS register table ....... None
+         | Is map 3d .................. True
+         | Number of points ........... 100
+         | Number of lines ............ 0
+         | Number of boundaries ....... 0
+         | Number of centroids ........ 0
+         | Number of faces ............ 0
+         | Number of kernels .......... 0
+         | Number of primitives ....... 100
+         | Number of nodes ............ 0
+         | Number of areas ............ 0
+         | Number of islands .......... 0
+         | Number of holes ............ 0
+         | Number of volumes .......... 0
+        >>> newmap = vmap.get_new_instance("new@PERMANENT")
+        >>> isinstance(newmap, VectorDataset)
+        True
+        >>> newstvds = vmap.get_new_stds_instance("new@PERMANENT")
+        >>> isinstance(newstvds, SpaceTimeVectorDataset)
+        True
+        >>> vmap.get_type()
+        'vector'
+        >>> vmap.get_stds_register()
+        >>> vmap.set_absolute_time(start_time=datetime(2001,1,1),
+        ...                        end_time=datetime(2012,1,1))
+        True
+        >>> vmap.get_absolute_time()
+        (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
+        >>> vmap.get_temporal_extent_as_tuple()
+        (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
+        >>> vmap.get_name()
+        'stvds_map_test_case'
+        >>> vmap.get_mapset() == mapset
+        True
+        >>> vmap.get_temporal_type()
+        'absolute'
+        >>> vmap.is_time_absolute()
+        True
+        >>> vmap.is_time_relative()
+        False
+        >>> grass.run_command("g.remove", vect=name)
+        0
+        >>> grass.del_temp_region()
+
+        @endcode
     """
     """
     def __init__(self, ident):
     def __init__(self, ident):
         AbstractMapDataset.__init__(self)
         AbstractMapDataset.__init__(self)
@@ -732,12 +937,36 @@ class VectorDataset(AbstractMapDataset):
     def has_grass_timestamp(self):
     def has_grass_timestamp(self):
         """!Check if a grass file bsased time stamp exists for this map.
         """!Check if a grass file bsased time stamp exists for this map.
         """
         """
-        if G_has_vector_timestamp(self.get_name(), self.get_layer(),
+        if libgis.G_has_vector_timestamp(self.get_name(), self.get_layer(),
                                   self.get_mapset()):
                                   self.get_mapset()):
             return True
             return True
         else:
         else:
             return False
             return False
 
 
+
+    def read_timestamp_from_grass(self):
+        """!Read the timestamp of this map from the map metadata
+           in the grass file system based spatial database and
+           set the internal time stamp that should be insert/updated
+           in the temporal database.
+        """
+
+        if not self.has_grass_timestamp():
+            return False
+
+        ts = libgis.TimeStamp()
+        check = libgis.G_read_vector_timestamp(self.get_name(), 
+                                               self.get_layer(),
+                                               self.get_mapset(),
+                                               byref(ts))
+
+        if check < 1:
+            core.error(_("Unable to read timestamp file "
+                         "for vector map <%s>" % (self.get_map_id())))
+            return False
+        
+        return self._set_timestamp_from_grass(ts)
+        
     def write_timestamp_to_grass(self):
     def write_timestamp_to_grass(self):
         """!Write the timestamp of this map into the map metadata in
         """!Write the timestamp of this map into the map metadata in
            the grass file system based spatial database.
            the grass file system based spatial database.