Skip to content

Commit

Permalink
fix: Fix DateTime according to DST (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuyKh authored Oct 7, 2024
1 parent 6f2e14e commit 4eafd4e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
6 changes: 6 additions & 0 deletions ims_envista/commons.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ def _verify_response_or_raise(response: ClientResponse) -> None:
raise ImsEnvistaApiClientAuthenticationError(
msg,
)
content_type = response.headers.get("Content-Type")
if content_type and "application/json" not in content_type:
msg = f"Invalid response from IMS - bad Content-Type: {content_type}"
raise ImsEnvistaApiClientError(
msg,
)
response.raise_for_status()


Expand Down
25 changes: 22 additions & 3 deletions ims_envista/meteo_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,31 @@ def __repr__(self) -> str:

tz = pytz.timezone("Asia/Jerusalem")


def _fix_datetime_offset(dt):
dt = dt.replace(tzinfo=None)
dt = tz.localize(dt)

# Get the UTC offset in seconds
offset_seconds = dt.utcoffset().total_seconds()

# Create a fixed timezone with the same offset and name
fixed_timezone = datetime.timezone(datetime.timedelta(seconds=offset_seconds), dt.tzname())

# Replace the pytz tzinfo with the fixed timezone
dt = dt.replace(tzinfo=fixed_timezone)

is_dst = dt.dst() != datetime.timedelta(0)
if is_dst:
dt = dt + datetime.timedelta(hours=1)

return dt,is_dst


def meteo_data_from_json(station_id: int, data: dict) -> MeteorologicalData:
"""Create a MeteorologicalData object from a JSON object."""
is_dst = bool(time.localtime(time.time()).tm_isdst)

dt = datetime.datetime.fromisoformat(data[API_DATETIME])
dt.replace(tzinfo=tz)
dt, is_dst = _fix_datetime_offset(dt)

channel_value_dict = {}
for channel_value in data[API_CHANNELS]:
Expand Down
32 changes: 20 additions & 12 deletions tests/unit/test_ims_envista.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from datetime import date, datetime, timedelta
from zoneinfo import ZoneInfo

import pytz
from aiohttp import ClientSession

from ims_envista import IMSEnvista
Expand All @@ -27,6 +28,7 @@ async def asyncSetUp(self) -> None:

# Initialize the session in an async context
self.session = ClientSession()
self.tz = pytz.timezone("Asia/Jerusalem")
self.ims = IMSEnvista(self.token, session=self.session)

async def asyncTearDown(self) -> None:
Expand Down Expand Up @@ -117,35 +119,38 @@ async def test_get_earliest_station_data_with_channel(self) -> None:
async def test_get_station_data_from_date(self) -> None:
"""Test get_station_data_from_date endpoint."""
station_data = await self.ims.get_station_data_from_date(
self.station_id, datetime.now(tz=ZoneInfo("Asia/Jerusalem"))
self.station_id, self.tz.localize(datetime.now())
)

assert station_data is not None
assert station_data.station_id == self.station_id
assert station_data.data is not None
assert len(station_data.data) > 0
for station_reading in station_data.data:
assert station_reading.datetime.date() == datetime.now(tz=ZoneInfo("Asia/Jerusalem")).date()
assert station_reading.datetime.date() == self.tz.localize(datetime.now()).date()


async def test_get_station_data_from_date_with_channel(self) -> None:
"""Test get_station_data_from_date endpoint with channel."""
station_data = await self.ims.get_station_data_from_date(
self.station_id, datetime.now(tz=ZoneInfo("Asia/Jerusalem")), self.channel_id
self.station_id, self.tz.localize(datetime.now()), self.channel_id
)

assert station_data is not None
assert station_data.station_id == self.station_id
assert station_data.data is not None
assert len(station_data.data) > 0
for station_reading in station_data.data:
assert station_reading.datetime.date() == datetime.now(tz=ZoneInfo("Asia/Jerusalem")).date()
assert station_reading.datetime.date() == self.tz.localize(datetime.now()).date()


async def test_get_station_data_by_date_range(self) -> None:
"""Test get_station_data_by_date_range endpoint."""
today = datetime.now(tz=ZoneInfo("Asia/Jerusalem"))
today = self.tz.localize(datetime.now())
today = today.replace(hour=0, minute=0, second=0, microsecond=0)
yesterday = today - timedelta(days=1)
# `hour=1` for DST fix cases
today = today.replace(hour=2, minute=0, second=0, microsecond=0)
station_data = await self.ims.get_station_data_by_date_range(
self.station_id, from_date=yesterday, to_date=today
)
Expand All @@ -156,14 +161,17 @@ async def test_get_station_data_by_date_range(self) -> None:
assert len(station_data.data) > 0
for station_reading in station_data.data:
assert station_reading.datetime >= to_date_time(yesterday)
assert station_reading.datetime < to_date_time(today)
assert station_reading.datetime < today
assert station_reading.td > 0


async def test_get_station_data_by_date_range_with_channel(self) -> None:
"""Test get_station_data_by_date_range endpoint with channel."""
today = datetime.now(tz=ZoneInfo("Asia/Jerusalem"))
today = self.tz.localize(datetime.now())
today = today.replace(hour=0, minute=0, second=0, microsecond=0)
yesterday = today - timedelta(days=1)
# `hour=1` for DST fix cases
today = today.replace(hour=2, minute=0, second=0, microsecond=0)
station_data = await self.ims.get_station_data_by_date_range(
self.station_id,
from_date=yesterday,
Expand All @@ -177,14 +185,14 @@ async def test_get_station_data_by_date_range_with_channel(self) -> None:
assert len(station_data.data) > 0
for station_reading in station_data.data:
assert station_reading.datetime >= to_date_time(yesterday)
assert station_reading.datetime < to_date_time(today)
assert station_reading.datetime < today
assert station_reading.td > 0


async def test_get_monthly_station_data(self) -> None:
"""Test get_monthly_station_data endpoint."""
year = datetime.now(tz=ZoneInfo("Asia/Jerusalem")).strftime("%Y")
month = datetime.now(tz=ZoneInfo("Asia/Jerusalem")).strftime("%m")
year = self.tz.localize(datetime.now()).strftime("%Y")
month = self.tz.localize(datetime.now()).strftime("%m")
station_data = await self.ims.get_monthly_station_data(
self.station_id, month=month, year=year
)
Expand All @@ -201,8 +209,8 @@ async def test_get_monthly_station_data(self) -> None:

async def test_get_monthly_station_data_with_channel(self) -> None:
"""Test get_monthly_station_data endpoint with channel."""
year = datetime.now(tz=ZoneInfo("Asia/Jerusalem")).strftime("%Y")
month = datetime.now(tz=ZoneInfo("Asia/Jerusalem")).strftime("%m")
year = self.tz.localize(datetime.now()).strftime("%Y")
month = self.tz.localize(datetime.now()).strftime("%m")
station_data = await self.ims.get_monthly_station_data(
self.station_id, channel_id=self.channel_id, month=month, year=year
)
Expand Down

0 comments on commit 4eafd4e

Please sign in to comment.