Correct today_at template function / filter (#60291)

Co-authored-by: Franck Nijhof <git@frenck.dev>
pull/60442/head
Erik Montnemery 2021-11-24 15:51:43 +01:00 committed by GitHub
parent d33457b7bc
commit 7b57033265
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 35 deletions

View File

@ -1689,16 +1689,16 @@ def random_every_time(context, values):
def today_at(time_str: str = "") -> datetime:
"""Record fetching now where the time has been replaced with value."""
start = dt_util.start_of_local_day(datetime.now())
today = dt_util.start_of_local_day()
if not time_str:
return today
dttime = start.time() if time_str == "" else dt_util.parse_time(time_str)
if (time_today := dt_util.parse_time(time_str)) is None:
raise ValueError(
f"could not convert {type(time_str).__name__} to datetime: '{time_str}'"
)
if dttime:
return datetime.combine(start.date(), dttime, tzinfo=dt_util.DEFAULT_TIME_ZONE)
raise ValueError(
f"could not convert {type(time_str).__name__} to datetime: '{time_str}'"
)
return datetime.combine(today, time_today, today.tzinfo)
def relative_time(value):

View File

@ -5,6 +5,7 @@ import math
import random
from unittest.mock import patch
from freezegun import freeze_time
import pytest
import voluptuous as vol
@ -1149,42 +1150,68 @@ def test_utcnow(mock_is_safe, hass):
assert info.has_time is True
@pytest.mark.parametrize(
"now, expected, expected_midnight, timezone_str",
[
# Host clock in UTC
(
"2021-11-24 03:00:00+00:00",
"2021-11-23T10:00:00-08:00",
"2021-11-23T00:00:00-08:00",
"America/Los_Angeles",
),
# Host clock in local time
(
"2021-11-23 19:00:00-08:00",
"2021-11-23T10:00:00-08:00",
"2021-11-23T00:00:00-08:00",
"America/Los_Angeles",
),
],
)
@patch(
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
return_value=True,
)
def test_today_at(mock_is_safe, hass):
def test_today_at(mock_is_safe, hass, now, expected, expected_midnight, timezone_str):
"""Test today_at method."""
now = dt_util.now()
with patch("homeassistant.util.dt.now", return_value=now):
now = now.replace(hour=10, minute=0, second=0, microsecond=0)
result = template.Template(
"{{ today_at('10:00').isoformat() }}",
hass,
).async_render()
assert result == now.isoformat()
freezer = freeze_time(now)
freezer.start()
result = template.Template(
"{{ today_at('10:00:00').isoformat() }}",
hass,
).async_render()
assert result == now.isoformat()
original_tz = dt_util.DEFAULT_TIME_ZONE
result = template.Template(
"{{ ('10:00:00' | today_at).isoformat() }}",
hass,
).async_render()
assert result == now.isoformat()
timezone = dt_util.get_time_zone(timezone_str)
dt_util.set_default_time_zone(timezone)
now = now.replace(hour=0)
result = template.Template(
"{{ today_at().isoformat() }}",
hass,
).async_render()
assert result == now.isoformat()
result = template.Template(
"{{ today_at('10:00').isoformat() }}",
hass,
).async_render()
assert result == expected
with pytest.raises(TemplateError):
template.Template("{{ today_at('bad') }}", hass).async_render()
result = template.Template(
"{{ today_at('10:00:00').isoformat() }}",
hass,
).async_render()
assert result == expected
result = template.Template(
"{{ ('10:00:00' | today_at).isoformat() }}",
hass,
).async_render()
assert result == expected
result = template.Template(
"{{ today_at().isoformat() }}",
hass,
).async_render()
assert result == expected_midnight
with pytest.raises(TemplateError):
template.Template("{{ today_at('bad') }}", hass).async_render()
freezer.stop()
dt_util.set_default_time_zone(original_tz)
@patch(