def test_temporal_extent_init_typing(self) -> None: # This test exists purely to test the typing of the intervals argument to # TemporalExtent start_datetime = str_to_datetime("2022-01-01T00:00:00Z") end_datetime = str_to_datetime("2022-01-31T23:59:59Z") _ = TemporalExtent([[start_datetime, end_datetime]])
def test_get_set_asset_datetime(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/item/sample-item-asset-properties.json")) item_datetime = item.datetime # No property on asset self.assertEqual(item.get_datetime(item.assets["thumbnail"]), item.datetime) # Property on asset self.assertNotEqual(item.get_datetime(item.assets["analytic"]), item.datetime) self.assertEqual( item.get_datetime(item.assets["analytic"]), str_to_datetime("2017-05-03T13:22:30.040Z"), ) item.set_datetime(str_to_datetime("2018-05-03T13:22:30.040Z"), item.assets["thumbnail"]) self.assertEqual(item.get_datetime(), item_datetime) self.assertEqual( item.get_datetime(item.assets["thumbnail"]), str_to_datetime("2018-05-03T13:22:30.040Z"), )
def test_apply(self): item = next(TestCases.test_case_2().get_all_items()) with self.assertRaises(ExtensionError): item.ext.timestamps item.ext.enable(Extensions.TIMESTAMPS) self.assertIn(Extensions.TIMESTAMPS, item.stac_extensions) item.ext.timestamps.apply( published=str_to_datetime("2020-01-03T06:45:55Z"), expires=str_to_datetime("2020-02-03T06:45:55Z"), unpublished=str_to_datetime("2020-03-03T06:45:55Z")) for d in [ item.ext.timestamps.published, item.ext.timestamps.expires, item.ext.timestamps.unpublished ]: self.assertIsInstance(d, datetime) for p in ('published', 'expires', 'unpublished'): self.assertIsInstance(item.properties[p], str) published_str = "2020-04-03T06:45:55Z" item.ext.timestamps.apply(published=str_to_datetime(published_str)) self.assertIsInstance(item.ext.timestamps.published, datetime) self.assertEqual(item.properties['published'], published_str) for d in [ item.ext.timestamps.expires, item.ext.timestamps.unpublished ]: self.assertIsNone(d) for p in ('expires', 'unpublished'): self.assertIsNone(item.properties[p])
def test_str_to_datetime(self) -> None: def _set_tzinfo(tz_str: Optional[str]) -> None: if tz_str is None: if "TZ" in os.environ: del os.environ["TZ"] else: os.environ["TZ"] = tz_str # time.tzset() only available for Unix/Linux if hasattr(time, "tzset"): time.tzset() utc_timestamp = "2015-06-27T10:25:31Z" prev_tz = os.environ.get("TZ") with self.subTest(tz=None): _set_tzinfo(None) utc_datetime = str_to_datetime(utc_timestamp) self.assertIs(utc_datetime.tzinfo, tz.tzutc()) self.assertIsNot(utc_datetime.tzinfo, tz.tzlocal()) with self.subTest(tz="UTC"): _set_tzinfo("UTC") utc_datetime = str_to_datetime(utc_timestamp) self.assertIs(utc_datetime.tzinfo, tz.tzutc()) self.assertIsNot(utc_datetime.tzinfo, tz.tzlocal()) with self.subTest(tz="US/Central"): _set_tzinfo("US/Central") utc_datetime = str_to_datetime(utc_timestamp) self.assertIs(utc_datetime.tzinfo, tz.tzutc()) self.assertIsNot(utc_datetime.tzinfo, tz.tzlocal()) if prev_tz is not None: _set_tzinfo(prev_tz)
def unpublished(self) -> Optional[RangeSummary[datetime]]: """Get or sets the summary of :attr:`TimestampsExtension.unpublished` values for this Collection. """ return map_opt( lambda s: RangeSummary(str_to_datetime(s.minimum), str_to_datetime(s.maximum)), self.summaries.get_range(UNPUBLISHED_PROP), )
def expires(self) -> Optional[RangeSummary[datetime]]: """Get or sets the summary of :attr:`TimestampsExtension.expires` values for this Collection. """ return map_opt( lambda s: RangeSummary(str_to_datetime(s.minimum), str_to_datetime(s.maximum)), self.summaries.get_range(EXPIRES_PROP), )
def stac( input, input_datetime, extension, collection, property, id, asset_name, asset_href, asset_mediatype, output, ): """Rasterio stac cli.""" property = property or {} if not input_datetime: input_datetime = datetime.datetime.utcnow() else: if "/" in input_datetime: start_datetime, end_datetime = input_datetime.split("/") property["start_datetime"] = datetime_to_str( str_to_datetime(start_datetime)) property["end_datetime"] = datetime_to_str( str_to_datetime(end_datetime)) input_datetime = None else: input_datetime = str_to_datetime(input_datetime) if asset_mediatype and asset_mediatype != "auto": asset_mediatype = MediaType[asset_mediatype] extensions = [e for e in extension if e] item = create_stac_item( input, input_datetime=input_datetime, extensions=extensions, collection=collection, properties=property, id=id, asset_name=asset_name, asset_href=asset_href, asset_media_type=asset_mediatype, ) if output: with open(output, "w") as f: f.write(json.dumps(item.to_dict(), separators=(",", ":"))) else: click.echo(json.dumps(item.to_dict(), separators=(",", ":")))
def test_common_metadata_end_datetime(self): x = self.ITEM_1.clone() end_datetime_str = "2018-01-01T13:31:30Z" end_datetime_dt = str_to_datetime(end_datetime_str) example_datetime_str = "2020-01-01T00:00:00" example_datetime_dt = str_to_datetime(example_datetime_str) self.assertEqual(x.common_metadata.end_datetime, end_datetime_dt) self.assertEqual(x.properties['end_datetime'], end_datetime_str) x.common_metadata.end_datetime = example_datetime_str self.assertEqual(x.common_metadata.end_datetime, example_datetime_dt) self.assertEqual(x.properties['end_datetime'], example_datetime_str)
def test_common_metadata_created(self): x = self.ITEM_2.clone() created_str = "2016-05-04T00:00:01Z" created_dt = str_to_datetime(created_str) example_datetime_str = "2020-01-01T00:00:00" example_datetime_dt = str_to_datetime(example_datetime_str) self.assertEqual(x.common_metadata.created, created_dt) self.assertEqual(x.properties['created'], created_str) x.common_metadata.created = example_datetime_str self.assertEqual(x.common_metadata.created, example_datetime_dt) self.assertEqual(x.properties['created'], example_datetime_str)
def test_common_metadata_start_datetime(self): x = self.ITEM_1.clone() start_datetime_str = "2018-01-01T13:21:30Z" start_datetime_dt = str_to_datetime(start_datetime_str) example_datetime_str = "2020-01-01T00:00:00Z" example_datetime_dt = str_to_datetime(example_datetime_str) self.assertEqual(x.common_metadata.start_datetime, start_datetime_dt) self.assertEqual(x.properties['start_datetime'], start_datetime_str) x.common_metadata.start_datetime = example_datetime_dt self.assertEqual(x.common_metadata.start_datetime, example_datetime_dt) self.assertEqual(x.properties['start_datetime'], example_datetime_str)
def test_common_metadata_updated(self): x = self.ITEM_2.clone() updated_str = "2017-01-01T00:30:55Z" updated_dt = str_to_datetime(updated_str) example_datetime_str = "2020-01-01T00:00:00" example_datetime_dt = str_to_datetime(example_datetime_str) self.assertEqual(x.common_metadata.updated, updated_dt) self.assertEqual(x.properties['updated'], updated_str) x.common_metadata.updated = example_datetime_str self.assertEqual(x.common_metadata.updated, example_datetime_dt) self.assertEqual(x.properties['updated'], example_datetime_str)
def from_dict( cls, d: Dict[str, Any], href: Optional[str] = None, root: Optional[Catalog] = None, migrate: bool = False, preserve_dict: bool = True, ) -> "Item": if migrate: info = identify_stac_object(d) d = migrate_to_latest(d, info) if not cls.matches_object_type(d): raise pystac.STACTypeError( f"{d} does not represent a {cls.__name__} instance") if preserve_dict: d = deepcopy(d) id = d.pop("id") geometry = d.pop("geometry") properties = d.pop("properties") bbox = d.pop("bbox", None) stac_extensions = d.get("stac_extensions") collection_id = d.pop("collection", None) datetime = properties.get("datetime") if datetime is not None: datetime = str_to_datetime(datetime) links = d.pop("links") assets = d.pop("assets") d.pop("type") d.pop("stac_version") item = cls( id=id, geometry=geometry, bbox=bbox, datetime=datetime, properties=properties, stac_extensions=stac_extensions, collection=collection_id, extra_fields=d, assets={k: Asset.from_dict(v) for k, v in assets.items()}, ) has_self_link = False for link in links: has_self_link |= link["rel"] == pystac.RelType.SELF item.add_link(Link.from_dict(link)) if not has_self_link and href is not None: item.add_link(Link.self_href(href)) if root: item.set_root(root) return item
def test_migrates_removed_extension(self): item = pystac.read_file( TestCases.get_path('data-files/examples/0.7.0/extensions/sar/' 'examples/sentinel1.json')) self.assertFalse('dtr' in item.stac_extensions) self.assertEqual(item.common_metadata.start_datetime, str_to_datetime("2018-11-03T23:58:55.121559Z"))
def test_anx_datetime(self) -> None: anx_datetime = str_to_datetime("2020-01-01T00:00:00Z") SatExtension.ext(self.item).apply(anx_datetime=anx_datetime) self.assertEqual(anx_datetime, SatExtension.ext(self.item).anx_datetime) self.assertNotIn(sat.RELATIVE_ORBIT_PROP, self.item.properties) self.assertIsNone(SatExtension.ext(self.item).relative_orbit) self.item.validate()
def get_created(self, asset=None): """Gets an Item or an Asset created time. If an Asset is supplied and the Item property exists on the Asset, returns the Asset's value. Otherwise returns the Item's value. Note: ``created`` and ``updated`` have different meaning depending on where they are used. If those fields are available in the Item `properties`, it's referencing to the creation and update times of the metadata. Having those fields in the Item `assets` refers to the creation and update times of the actual data linked to in the Asset Object. Returns: datetime """ if asset is None or 'created' not in asset.properties: created = self.properties.get('created') else: created = asset.properties.get('created') if created: created = str_to_datetime(created) return created
def setUp(self): self.maxDiff = None self.example_uri = TestCases.get_path( 'data-files/timestamps/example-landsat8.json') with open(self.example_uri) as f: self.item_dict = json.load(f) self.sample_datetime_str = "2020-01-01T00:00:00Z" self.sample_datetime = str_to_datetime(self.sample_datetime_str)
def datetime(self) -> datetime: time = self.product_info_node.find_text('PRODUCT_START_TIME') if time is None: raise ValueError( 'Cannot determine product start time using product metadata ' f'at {self.href}') else: return str_to_datetime(time)
def test_published(self) -> None: timestamps_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("published", timestamps_item.properties) timestamps_published = TimestampsExtension.ext( timestamps_item).published self.assertIsInstance(timestamps_published, datetime) self.assertEqual( datetime_to_str(get_opt(timestamps_published)), timestamps_item.properties["published"], ) # Set TimestampsExtension.ext( timestamps_item).published = self.sample_datetime self.assertEqual(self.sample_datetime_str, timestamps_item.properties["published"]) # Get from Asset asset_no_prop = timestamps_item.assets["red"] asset_prop = timestamps_item.assets["blue"] self.assertEqual( TimestampsExtension.ext(asset_no_prop).published, TimestampsExtension.ext(timestamps_item).published, ) self.assertEqual( TimestampsExtension.ext(asset_prop).published, str_to_datetime("2018-11-02T00:00:00Z"), ) # # Set to Asset asset_value = str_to_datetime("2019-02-02T00:00:00Z") TimestampsExtension.ext(asset_no_prop).published = asset_value self.assertNotEqual( TimestampsExtension.ext(asset_no_prop).published, TimestampsExtension.ext(timestamps_item).published, ) self.assertEqual( TimestampsExtension.ext(asset_no_prop).published, asset_value) # Validate timestamps_item.validate()
def test_migrates_removed_extension(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.8.1/extensions/sar/examples/sentinel1.json" )) self.assertFalse("dtr" in item.stac_extensions) self.assertEqual( item.common_metadata.start_datetime, str_to_datetime("2018-11-03T23:58:55.121559Z"), )
def _timestamp_getter(self, key, asset=None): if asset is not None and key in asset.properties: timestamp_str = asset.properties.get(key) else: timestamp_str = self.item.properties.get(key) timestamp = None if timestamp_str is not None: timestamp = str_to_datetime(timestamp_str) return timestamp
def test_get_set_asset_datetime(self): item = pystac.read_file( TestCases.get_path( 'data-files/item/sample-item-asset-properties.json')) item_datetime = item.datetime # No property on asset self.assertEqual(item.get_datetime(item.assets['thumbnail']), item.datetime) # Property on asset self.assertNotEqual(item.get_datetime(item.assets['analytic']), item.datetime) self.assertEqual(item.get_datetime(item.assets['analytic']), str_to_datetime("2017-05-03T13:22:30.040Z")) item.set_datetime(str_to_datetime("2018-05-03T13:22:30.040Z"), item.assets['thumbnail']) self.assertEqual(item.get_datetime(), item_datetime) self.assertEqual(item.get_datetime(item.assets['thumbnail']), str_to_datetime("2018-05-03T13:22:30.040Z"))
def test_updated(self) -> None: item = self.item.clone() cm = item.common_metadata analytic = item.assets["analytic"] analytic_cm = CommonMetadata(analytic) thumbnail = item.assets["thumbnail"] thumbnail_cm = CommonMetadata(thumbnail) item_value = cm.updated a2_known_value = utils.str_to_datetime("2017-05-18T13:22:30.040Z") # Get self.assertNotEqual(thumbnail_cm.updated, item_value) self.assertEqual(thumbnail_cm.updated, a2_known_value) # Set set_value = utils.str_to_datetime("2014-05-18T13:22:30.040Z") analytic_cm.updated = set_value self.assertEqual(analytic_cm.updated, set_value) self.assertEqual(analytic.to_dict()["updated"], utils.datetime_to_str(set_value))
def created(self): """Get or set the metadata file's creation date. All datetime attributes have setters that can take either a string or a datetime, but always stores the attribute as a string Returns: datetime: Creation date and time of the metadata file """ created = self.properties.get('created') if created: created = str_to_datetime(created) return created
def from_dict(d: Dict[str, Any]) -> "TemporalExtent": """Constructs an TemporalExtent from a dict. Returns: TemporalExtent: The TemporalExtent deserialized from the JSON dict. """ parsed_intervals: List[List[Optional[datetime]]] = [] for i in d["interval"]: start = None end = None if i[0]: start = str_to_datetime(i[0]) if i[1]: end = str_to_datetime(i[1]) parsed_intervals.append([start, end]) return TemporalExtent( intervals=parsed_intervals, extra_fields={k: v for k, v in d.items() if k != "interval"}, )
def start_datetime(self): """Get or set the item's start_datetime. All datetime attributes have setters that can take either a string or a datetime, but always stores the attribute as a string Returns: datetime: Start date and time for the item """ start_datetime = self.properties.get('start_datetime') if start_datetime: start_datetime = str_to_datetime(start_datetime) return start_datetime
def end_datetime(self): """Get or set the item's end_datetime. All datetime attributes have setters that can take either a string or a datetime, but always stores the attribute as a string Returns: datetime: End date and time for the item """ end_datetime = self.properties.get('end_datetime') if end_datetime: end_datetime = str_to_datetime(end_datetime) return end_datetime
def test_asset_updated(self): item = pystac.read_file( TestCases.get_path( 'data-files/item/sample-item-asset-properties.json')) cm = item.common_metadata item_value = cm.updated a2_known_value = str_to_datetime("2017-05-18T13:22:30.040Z") # Get a1_value = cm.get_updated(item.assets['analytic']) a2_value = cm.get_updated(item.assets['thumbnail']) self.assertEqual(a1_value, item_value) self.assertNotEqual(a2_value, item_value) self.assertEqual(a2_value, a2_known_value) # Set set_value = str_to_datetime("2014-05-18T13:22:30.040Z") cm.set_updated(set_value, item.assets['analytic']) new_a1_value = cm.get_updated(item.assets['analytic']) self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.updated, item_value)
def item_datetime(self) -> datetime: tod_xpath = 'GranuleURMetaData/SingleDateTime/TimeofDay' date_xpath = 'GranuleURMetaData/SingleDateTime/CalendarDate' tod = self.root.find_text(tod_xpath) if tod is None: raise self._xml_error(tod_xpath) date = self.root.find_text(date_xpath) if date is None: raise self._xml_error(date_xpath) return str_to_datetime(f'{date}T{tod}Z')
def get_datetime(self, asset=None): """Gets an Item or an Asset datetime. If an Asset is supplied and the Item property exists on the Asset, returns the Asset's value. Otherwise returns the Item's value. Returns: datetime or None """ if asset is None or 'datetime' not in asset.properties: return self.datetime else: return str_to_datetime(asset.properties.get('datetime'))
def test_published(self): timestamps_item = pystac.read_file(self.example_uri) # Get self.assertIn("published", timestamps_item.properties) timestamps_published = timestamps_item.ext.timestamps.published self.assertIsInstance(timestamps_published, datetime) self.assertEqual(datetime_to_str(timestamps_published), timestamps_item.properties['published']) # Set timestamps_item.ext.timestamps.published = self.sample_datetime self.assertEqual(self.sample_datetime_str, timestamps_item.properties['published']) # Get from Asset asset_no_prop = timestamps_item.assets['red'] asset_prop = timestamps_item.assets['blue'] self.assertEqual( timestamps_item.ext.timestamps.get_published(asset_no_prop), timestamps_item.ext.timestamps.get_published()) self.assertEqual( timestamps_item.ext.timestamps.get_published(asset_prop), str_to_datetime("2018-11-02T00:00:00Z")) # # Set to Asset asset_value = str_to_datetime("2019-02-02T00:00:00Z") timestamps_item.ext.timestamps.set_published(asset_value, asset_no_prop) self.assertNotEqual( timestamps_item.ext.timestamps.get_published(asset_no_prop), timestamps_item.ext.timestamps.get_published()) self.assertEqual( timestamps_item.ext.timestamps.get_published(asset_no_prop), asset_value) # Validate timestamps_item.validate()