Skip to content

Commit

Permalink
refactor TimeStamp to use KmlDateTime
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed Jan 14, 2023
1 parent 28115e1 commit 114f693
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 60 deletions.
14 changes: 8 additions & 6 deletions fastkml/kml.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,17 @@ def style_url(self, styleurl: Union[str, StyleUrl, None]) -> None:
raise ValueError

@property
def time_stamp(self):
def time_stamp(self) -> Optional[TimeStamp]:
"""This just returns the datetime portion of the timestamp"""
if self._timestamp is not None:
return self._timestamp.timestamp[0]
if self._timestamp:
return self._timestamp

@time_stamp.setter
def time_stamp(self, dt):
self._timestamp = None if dt is None else TimeStamp(timestamp=dt)
if self._timespan is not None:
def time_stamp(self, timestamp: Optional[TimeStamp]) -> None:
self._timestamp = timestamp
if self._timespan is None:
return
if timestamp:
logger.warning("Setting a TimeStamp, TimeSpan deleted")
self._timespan = None

Expand Down
20 changes: 13 additions & 7 deletions fastkml/times.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ def __bool__(self) -> bool:
"""Return True if the date or datetime is valid."""
return isinstance(self.dt, date)

def __eq__(self, other: object) -> bool:
"""Return True if the two objects are equal."""
return (
self.dt == other.dt and self.resolution == other.resolution
if isinstance(other, KmlDateTime)
else False
)

def __str__(self) -> str:
"""Return the KML DateTime string representation of the object."""
if self.resolution == DateTimeResolution.year:
Expand Down Expand Up @@ -123,7 +131,7 @@ def parse(cls, datestr: str) -> Optional["KmlDateTime"]:
month = int(ym.group("month"))
dt = datetime(year, month, 1)
resolution = DateTimeResolution.year_month
elif len(datestr) in {8, 10}: # 8 is YYYYMMDDS
elif len(datestr) in {8, 10}: # 8 is YYYYMMDD, 10 is YYYY-MM-DD
dt = dateutil.parser.parse(datestr)
resolution = DateTimeResolution.date
elif len(datestr) > 10:
Expand Down Expand Up @@ -212,26 +220,24 @@ def __init__(
ns: Optional[str] = None,
id: Optional[str] = None,
target_id: Optional[str] = None,
timestamp: Optional[Union[date, datetime]] = None,
resolution: Optional[str] = None,
timestamp: Optional[KmlDateTime] = None,
) -> None:
super().__init__(ns=ns, id=id, target_id=target_id)
resolution = self.get_resolution(timestamp, resolution)
self.timestamp = (timestamp, resolution)
self.timestamp = timestamp

def etree_element(self) -> Element:
element = super().etree_element()
when = config.etree.SubElement( # type: ignore[attr-defined]
element, f"{self.ns}when"
)
when.text = self.date_to_string(*self.timestamp)
when.text = str(self.timestamp)
return element

def from_element(self, element: Element) -> None:
super().from_element(element)
when = element.find(f"{self.ns}when")
if when is not None:
self.timestamp = self.parse_str(when.text)
self.timestamp = KmlDateTime.parse(when.text)


class TimeSpan(_TimePrimitive):
Expand Down
10 changes: 4 additions & 6 deletions fastkml/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ def __init__(
self._timestamp = time_primitive

@property
def timestamp(self) -> Optional[datetime.datetime]:
if self._timestamp is not None:
return self._timestamp.timestamp[0]
return None
def timestamp(self) -> TimeStamp:
return self._timestamp

@timestamp.setter
def timestamp(self, dt: datetime.datetime) -> None:
self._timestamp = None if dt is None else TimeStamp(timestamp=dt)
def timestamp(self, timestamp: Optional[TimeStamp]) -> None:
self._timestamp = timestamp
if self._timestamp is not None:
logger.warning("Setting a TimeStamp, TimeSpan deleted")
self._timespan = None
Expand Down
60 changes: 22 additions & 38 deletions tests/times_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,34 +181,18 @@ class TestStdLibrary(StdLibrary):

def test_timestamp(self):
now = datetime.datetime.now()
ts = kml.TimeStamp(timestamp=now)
assert ts.timestamp == (now, "dateTime")
dt = KmlDateTime(now)
ts = kml.TimeStamp(timestamp=dt)
assert ts.timestamp.dt == now
assert ts.timestamp.resolution == DateTimeResolution.datetime
assert "TimeStamp>" in str(ts.to_string())
assert "when>" in str(ts.to_string())
assert now.isoformat() in str(ts.to_string())
y2k = datetime.date(2000, 1, 1)
y2k = KmlDateTime(datetime.date(2000, 1, 1))
ts = kml.TimeStamp(timestamp=y2k)
assert ts.timestamp == (y2k, "date")
assert ts.timestamp == y2k
assert "2000-01-01" in str(ts.to_string())

def test_timestamp_resolution(self):
now = datetime.datetime.now()
ts = kml.TimeStamp(timestamp=now)
assert now.isoformat() in str(ts.to_string())
ts.timestamp = (now, "date")
assert now.date().isoformat() in str(ts.to_string())
assert now.isoformat() not in str(ts.to_string())
year = str(now.year)
ym = now.strftime("%Y-%m")
ts.timestamp = (now, "gYearMonth")
assert ym in str(ts.to_string())
assert now.date().isoformat() not in str(ts.to_string())
ts.timestamp = (now, "gYear")
assert year in str(ts.to_string())
assert ym not in str(ts.to_string())
ts.timestamp = None
pytest.raises(TypeError, ts.to_string)

def test_timespan(self):
now = datetime.datetime.now()
y2k = datetime.datetime(2000, 1, 1)
Expand All @@ -229,12 +213,12 @@ def test_timespan(self):
def test_feature_timestamp(self):
now = datetime.datetime.now()
f = kml.Document()
f.time_stamp = now
assert f.time_stamp == now
f.time_stamp = kml.TimeStamp(timestamp=KmlDateTime(now))
assert f.time_stamp.timestamp == KmlDateTime(now)
assert now.isoformat() in str(f.to_string())
assert "TimeStamp>" in str(f.to_string())
assert "when>" in str(f.to_string())
f.time_stamp = now.date()
f.time_stamp = kml.TimeStamp(timestamp=KmlDateTime(now.date()))
assert now.date().isoformat() in str(f.to_string())
assert now.isoformat() not in str(f.to_string())
f.time_stamp = None
Expand Down Expand Up @@ -276,7 +260,7 @@ def test_feature_timespan_stamp(self):
assert "TimeStamp>" not in str(f.to_string())
assert "when>" not in str(f.to_string())
# when we set a timestamp an existing timespan will be deleted
f.time_stamp = now
f.time_stamp = kml.TimeStamp(timestamp=KmlDateTime(now))
assert now.isoformat() in str(f.to_string())
assert "TimeStamp>" in str(f.to_string())
assert "when>" in str(f.to_string())
Expand Down Expand Up @@ -309,35 +293,35 @@ def test_read_timestamp(self):
"""

ts.from_string(doc)
assert ts.timestamp[1] == "gYear"
assert ts.timestamp[0] == datetime.datetime(1997, 1, 1, 0, 0)
assert ts.timestamp.resolution == DateTimeResolution.year
assert ts.timestamp.dt == datetime.datetime(1997, 1, 1, 0, 0)
doc = """
<TimeStamp>
<when>1997-07</when>
</TimeStamp>
"""

ts.from_string(doc)
assert ts.timestamp[1] == "gYearMonth"
assert ts.timestamp[0] == datetime.datetime(1997, 7, 1, 0, 0)
assert ts.timestamp.resolution == DateTimeResolution.year_month
assert ts.timestamp.dt == datetime.datetime(1997, 7, 1, 0, 0)
doc = """
<TimeStamp>
<when>199808</when>
</TimeStamp>
"""

ts.from_string(doc)
assert ts.timestamp[1] == "gYearMonth"
assert ts.timestamp[0] == datetime.datetime(1998, 8, 1, 0, 0)
assert ts.timestamp.resolution == DateTimeResolution.year_month
assert ts.timestamp.dt == datetime.datetime(1998, 8, 1, 0, 0)
doc = """
<TimeStamp>
<when>1997-07-16</when>
</TimeStamp>
"""

ts.from_string(doc)
assert ts.timestamp[1] == "date"
assert ts.timestamp[0] == datetime.datetime(1997, 7, 16, 0, 0)
assert ts.timestamp.resolution == DateTimeResolution.date
assert ts.timestamp.dt == datetime.datetime(1997, 7, 16, 0, 0)
# dateTime (YYYY-MM-DDThh:mm:ssZ)
# Here, T is the separator between the calendar and the hourly notation
# of time, and Z indicates UTC. (Seconds are required.)
Expand All @@ -348,8 +332,8 @@ def test_read_timestamp(self):
"""

ts.from_string(doc)
assert ts.timestamp[1] == "dateTime"
assert ts.timestamp[0] == datetime.datetime(
assert ts.timestamp.resolution == DateTimeResolution.datetime
assert ts.timestamp.dt == datetime.datetime(
1997, 7, 16, 7, 30, 15, tzinfo=tzutc()
)
doc = """
Expand All @@ -359,8 +343,8 @@ def test_read_timestamp(self):
"""

ts.from_string(doc)
assert ts.timestamp[1] == "dateTime"
assert ts.timestamp[0] == datetime.datetime(
assert ts.timestamp.resolution == DateTimeResolution.datetime
assert ts.timestamp.dt == datetime.datetime(
1997, 7, 16, 10, 30, 15, tzinfo=tzoffset(None, 10800)
)

Expand Down
6 changes: 3 additions & 3 deletions tests/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def test_camera_read(self) -> None:
def test_create_look_at(self) -> None:
time_stamp = times.TimeStamp(
id="time-span-id",
timestamp=datetime.datetime(2019, 1, 1),
timestamp=times.KmlDateTime(datetime.datetime(2019, 1, 1)),
)

look_at = views.LookAt(
Expand All @@ -121,7 +121,7 @@ def test_create_look_at(self) -> None:
assert look_at.longitude == 60
assert look_at.id == "look-at-id"
assert look_at.target_id == "target-look-at-id"
assert look_at.timestamp == datetime.datetime(2019, 1, 1)
assert look_at.timestamp.timestamp.dt == datetime.datetime(2019, 1, 1)
assert look_at.begin is None
assert look_at.end is None
assert look_at.to_string()
Expand Down Expand Up @@ -153,7 +153,7 @@ def test_look_at_read(self) -> None:
assert look_at.longitude == 60
assert look_at.id == "look-at-id"
assert look_at.target_id == "target-look-at-id"
assert look_at.timestamp == datetime.datetime(2019, 1, 1)
assert look_at.timestamp.timestamp.dt == datetime.datetime(2019, 1, 1)
assert look_at.begin is None
assert look_at.end is None

Expand Down

0 comments on commit 114f693

Please sign in to comment.