Fix process_datetime_to_timestamp and add test coverage (#71755)
parent
8ab27f26b9
commit
1d9fb4bca8
|
@ -55,6 +55,10 @@ SCHEMA_VERSION = 28
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# EPOCHORDINAL is not exposed as a constant
|
||||
# https://github.com/python/cpython/blob/3.10/Lib/zoneinfo/_zoneinfo.py#L12
|
||||
EPOCHORDINAL = datetime(1970, 1, 1).toordinal()
|
||||
|
||||
DB_TIMEZONE = "+00:00"
|
||||
|
||||
TABLE_EVENTS = "events"
|
||||
|
@ -630,10 +634,22 @@ def process_timestamp_to_utc_isoformat(ts: datetime | None) -> str | None:
|
|||
|
||||
|
||||
def process_datetime_to_timestamp(ts: datetime) -> float:
|
||||
"""Process a timestamp into a unix timestamp."""
|
||||
if ts.tzinfo == dt_util.UTC:
|
||||
return ts.timestamp()
|
||||
return ts.replace(tzinfo=dt_util.UTC).timestamp()
|
||||
"""Process a datebase datetime to epoch.
|
||||
|
||||
Mirrors the behavior of process_timestamp_to_utc_isoformat
|
||||
except it returns the epoch time.
|
||||
"""
|
||||
if ts.tzinfo is None:
|
||||
# Taken from
|
||||
# https://github.com/python/cpython/blob/3.10/Lib/zoneinfo/_zoneinfo.py#L185
|
||||
return (
|
||||
(ts.toordinal() - EPOCHORDINAL) * 86400
|
||||
+ ts.hour * 3600
|
||||
+ ts.minute * 60
|
||||
+ ts.second
|
||||
+ (ts.microsecond / 1000000)
|
||||
)
|
||||
return ts.timestamp()
|
||||
|
||||
|
||||
class LazyState(State):
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from datetime import datetime, timedelta
|
||||
from unittest.mock import PropertyMock
|
||||
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
|
@ -14,6 +15,7 @@ from homeassistant.components.recorder.models import (
|
|||
RecorderRuns,
|
||||
StateAttributes,
|
||||
States,
|
||||
process_datetime_to_timestamp,
|
||||
process_timestamp,
|
||||
process_timestamp_to_utc_isoformat,
|
||||
)
|
||||
|
@ -333,3 +335,73 @@ async def test_lazy_state_handles_same_last_updated_and_last_changed(caplog):
|
|||
"last_updated": "2020-06-12T03:04:01.000323+00:00",
|
||||
"state": "off",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"time_zone", ["Europe/Berlin", "America/Chicago", "US/Hawaii", "UTC"]
|
||||
)
|
||||
def test_process_datetime_to_timestamp(time_zone, hass):
|
||||
"""Test we can handle processing database datatimes to timestamps."""
|
||||
hass.config.set_time_zone(time_zone)
|
||||
utc_now = dt_util.utcnow()
|
||||
assert process_datetime_to_timestamp(utc_now) == utc_now.timestamp()
|
||||
now = dt_util.now()
|
||||
assert process_datetime_to_timestamp(now) == now.timestamp()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"time_zone", ["Europe/Berlin", "America/Chicago", "US/Hawaii", "UTC"]
|
||||
)
|
||||
def test_process_datetime_to_timestamp_freeze_time(time_zone, hass):
|
||||
"""Test we can handle processing database datatimes to timestamps.
|
||||
|
||||
This test freezes time to make sure everything matches.
|
||||
"""
|
||||
hass.config.set_time_zone(time_zone)
|
||||
utc_now = dt_util.utcnow()
|
||||
with freeze_time(utc_now):
|
||||
epoch = utc_now.timestamp()
|
||||
assert process_datetime_to_timestamp(dt_util.utcnow()) == epoch
|
||||
now = dt_util.now()
|
||||
assert process_datetime_to_timestamp(now) == epoch
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"time_zone", ["Europe/Berlin", "America/Chicago", "US/Hawaii", "UTC"]
|
||||
)
|
||||
async def test_process_datetime_to_timestamp_mirrors_utc_isoformat_behavior(
|
||||
time_zone, hass
|
||||
):
|
||||
"""Test process_datetime_to_timestamp mirrors process_timestamp_to_utc_isoformat."""
|
||||
hass.config.set_time_zone(time_zone)
|
||||
datetime_with_tzinfo = datetime(2016, 7, 9, 11, 0, 0, tzinfo=dt.UTC)
|
||||
datetime_without_tzinfo = datetime(2016, 7, 9, 11, 0, 0)
|
||||
est = dt_util.get_time_zone("US/Eastern")
|
||||
datetime_est_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=est)
|
||||
est = dt_util.get_time_zone("US/Eastern")
|
||||
datetime_est_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=est)
|
||||
nst = dt_util.get_time_zone("Canada/Newfoundland")
|
||||
datetime_nst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=nst)
|
||||
hst = dt_util.get_time_zone("US/Hawaii")
|
||||
datetime_hst_timezone = datetime(2016, 7, 9, 11, 0, 0, tzinfo=hst)
|
||||
|
||||
assert (
|
||||
process_datetime_to_timestamp(datetime_with_tzinfo)
|
||||
== dt_util.parse_datetime("2016-07-09T11:00:00+00:00").timestamp()
|
||||
)
|
||||
assert (
|
||||
process_datetime_to_timestamp(datetime_without_tzinfo)
|
||||
== dt_util.parse_datetime("2016-07-09T11:00:00+00:00").timestamp()
|
||||
)
|
||||
assert (
|
||||
process_datetime_to_timestamp(datetime_est_timezone)
|
||||
== dt_util.parse_datetime("2016-07-09T15:00:00+00:00").timestamp()
|
||||
)
|
||||
assert (
|
||||
process_datetime_to_timestamp(datetime_nst_timezone)
|
||||
== dt_util.parse_datetime("2016-07-09T13:30:00+00:00").timestamp()
|
||||
)
|
||||
assert (
|
||||
process_datetime_to_timestamp(datetime_hst_timezone)
|
||||
== dt_util.parse_datetime("2016-07-09T21:00:00+00:00").timestamp()
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue