Skip to content

rework datetime values #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stac_fastapi/elasticsearch/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"pytest-asyncio",
"pre-commit",
"requests",
"ciso8601",
],
"docs": ["mkdocs", "mkdocs-material", "pdocs"],
"server": ["uvicorn[standard]>=0.12.0,<0.14.0"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""A few datetime methods."""
from datetime import datetime, timezone

from pystac.utils import datetime_to_str


def now_in_utc() -> datetime:
"""Return a datetime value of now with the UTC timezone applied."""
return datetime.now(timezone.utc)


def now_to_rfc3339_str() -> str:
"""Return an RFC 3339 string representing now."""
return datetime_to_str(now_in_utc())
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"""Serializers."""
import abc
from datetime import datetime
from typing import TypedDict

import attr
from stac_pydantic.shared import DATETIME_RFC339

from stac_fastapi.elasticsearch.datetime_utils import now_to_rfc3339_str
from stac_fastapi.types import stac as stac_types
from stac_fastapi.types.links import CollectionLinks, ItemLinks, resolve_links

Expand Down Expand Up @@ -42,10 +41,10 @@ def stac_to_db(cls, stac_data: TypedDict, base_url: str) -> stac_types.Item:
v = float(v)
wave.update({k: v})

now = datetime.utcnow().strftime(DATETIME_RFC339)
now = now_to_rfc3339_str()
if "created" not in stac_data["properties"]:
stac_data["properties"]["created"] = str(now)
stac_data["properties"]["updated"] = str(now)
stac_data["properties"]["created"] = now
stac_data["properties"]["updated"] = now
return stac_data

@classmethod
Expand Down
34 changes: 19 additions & 15 deletions stac_fastapi/elasticsearch/tests/resources/test_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@
from random import randint
from urllib.parse import parse_qs, urlparse, urlsplit

import ciso8601
import pystac
import pytest
from geojson_pydantic.geometries import Polygon
from stac_pydantic.shared import DATETIME_RFC339
from pystac.utils import datetime_to_str

from stac_fastapi.elasticsearch.core import CoreCrudClient
from stac_fastapi.elasticsearch.datetime_utils import now_to_rfc3339_str
from stac_fastapi.types.core import LandingPageMixin


def rfc3339_str_to_datetime(s: str) -> datetime:
return ciso8601.parse_rfc3339(s)


@pytest.mark.skip(reason="unknown")
def test_create_and_delete_item(app_client, load_test_data):
"""Test creation and deletion of a single item (transactions extension)"""
Expand Down Expand Up @@ -275,7 +281,7 @@ def test_pagination(app_client, load_test_data):
def test_item_timestamps(app_client, load_test_data):
"""Test created and updated timestamps (common metadata)"""
test_item = load_test_data("test_item.json")
start_time = datetime.utcnow().strftime(DATETIME_RFC339)
start_time = now_to_rfc3339_str()
time.sleep(1)
# Confirm `created` timestamp
resp = app_client.post(
Expand All @@ -285,9 +291,7 @@ def test_item_timestamps(app_client, load_test_data):
created_dt = item["properties"]["created"]
time.sleep(1)
assert resp.status_code == 200
assert (
str(start_time) < created_dt < str(datetime.utcnow().strftime(DATETIME_RFC339))
)
assert start_time < created_dt < now_to_rfc3339_str()

time.sleep(1)
# Confirm `updated` timestamp
Expand Down Expand Up @@ -364,13 +368,13 @@ def test_item_search_temporal_query_post(app_client, load_test_data):
)
assert resp.status_code == 200

item_date = datetime.strptime(test_item["properties"]["datetime"], DATETIME_RFC339)
item_date = rfc3339_str_to_datetime(test_item["properties"]["datetime"])
item_date = item_date + timedelta(seconds=1)

params = {
"collections": [test_item["collection"]],
"intersects": test_item["geometry"],
"datetime": f"../{item_date.strftime(DATETIME_RFC339)}",
"datetime": f"../{datetime_to_str(item_date)}",
}
resp = app_client.post("/search", json=params)
resp_json = resp.json()
Expand All @@ -391,14 +395,14 @@ def test_item_search_temporal_window_post(app_client, load_test_data):
)
assert resp.status_code == 200

item_date = datetime.strptime(test_item["properties"]["datetime"], DATETIME_RFC339)
item_date = rfc3339_str_to_datetime(test_item["properties"]["datetime"])
item_date_before = item_date - timedelta(seconds=1)
item_date_after = item_date + timedelta(seconds=1)

params = {
"collections": [test_item["collection"]],
"intersects": test_item["geometry"],
"datetime": f"{item_date_before.strftime(DATETIME_RFC339)}/{item_date_after.strftime(DATETIME_RFC339)}",
"datetime": f"{datetime_to_str(item_date_before)}/{datetime_to_str(item_date_after)}",
}
resp = app_client.post("/search", json=params)
resp_json = resp.json()
Expand Down Expand Up @@ -438,7 +442,7 @@ def test_item_search_temporal_open_window(app_client, load_test_data):
def test_item_search_sort_post(app_client, load_test_data):
"""Test POST search with sorting (sort extension)"""
first_item = load_test_data("test_item.json")
item_date = datetime.strptime(first_item["properties"]["datetime"], DATETIME_RFC339)
item_date = rfc3339_str_to_datetime(first_item["properties"]["datetime"])
resp = app_client.post(
f"/collections/{first_item['collection']}/items", json=first_item
)
Expand All @@ -447,7 +451,7 @@ def test_item_search_sort_post(app_client, load_test_data):
second_item = load_test_data("test_item.json")
second_item["id"] = "another-item"
another_item_date = item_date - timedelta(days=1)
second_item["properties"]["datetime"] = another_item_date.strftime(DATETIME_RFC339)
second_item["properties"]["datetime"] = datetime_to_str(another_item_date)
resp = app_client.post(
f"/collections/{second_item['collection']}/items", json=second_item
)
Expand Down Expand Up @@ -542,14 +546,14 @@ def test_item_search_temporal_window_get(app_client, load_test_data):
)
assert resp.status_code == 200

item_date = datetime.strptime(test_item["properties"]["datetime"], DATETIME_RFC339)
item_date = rfc3339_str_to_datetime(test_item["properties"]["datetime"])
item_date_before = item_date - timedelta(seconds=1)
item_date_after = item_date + timedelta(seconds=1)

params = {
"collections": test_item["collection"],
"bbox": ",".join([str(coord) for coord in test_item["bbox"]]),
"datetime": f"{item_date_before.strftime(DATETIME_RFC339)}/{item_date_after.strftime(DATETIME_RFC339)}",
"datetime": f"{datetime_to_str(item_date_before)}/{datetime_to_str(item_date_after)}",
}
resp = app_client.get("/search", params=params)
resp_json = resp.json()
Expand All @@ -565,7 +569,7 @@ def test_item_search_temporal_window_get(app_client, load_test_data):
def test_item_search_sort_get(app_client, load_test_data):
"""Test GET search with sorting (sort extension)"""
first_item = load_test_data("test_item.json")
item_date = datetime.strptime(first_item["properties"]["datetime"], DATETIME_RFC339)
item_date = rfc3339_str_to_datetime(first_item["properties"]["datetime"])
resp = app_client.post(
f"/collections/{first_item['collection']}/items", json=first_item
)
Expand All @@ -574,7 +578,7 @@ def test_item_search_sort_get(app_client, load_test_data):
second_item = load_test_data("test_item.json")
second_item["id"] = "another-item"
another_item_date = item_date - timedelta(days=1)
second_item["properties"]["datetime"] = another_item_date.strftime(DATETIME_RFC339)
second_item["properties"]["datetime"] = datetime_to_str(another_item_date)
resp = app_client.post(
f"/collections/{second_item['collection']}/items", json=second_item
)
Expand Down