mirror of
https://github.com/home-assistant/core.git
synced 2025-12-25 21:47:08 +00:00
791 lines
23 KiB
Python
791 lines
23 KiB
Python
"""Test datetime template functions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from types import MappingProxyType
|
|
from typing import Any
|
|
from unittest.mock import patch
|
|
|
|
from freezegun import freeze_time
|
|
import pytest
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import TemplateError
|
|
from homeassistant.util import dt as dt_util
|
|
from homeassistant.util.read_only_dict import ReadOnlyDict
|
|
|
|
from tests.helpers.template.helpers import render, render_to_info
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("value", "expected"),
|
|
[
|
|
([1, 2], False),
|
|
({1, 2}, False),
|
|
({"a": 1, "b": 2}, False),
|
|
(ReadOnlyDict({"a": 1, "b": 2}), False),
|
|
(MappingProxyType({"a": 1, "b": 2}), False),
|
|
("abc", False),
|
|
(b"abc", False),
|
|
((1, 2), False),
|
|
(datetime(2024, 1, 1, 0, 0, 0), True),
|
|
],
|
|
)
|
|
def test_is_datetime(hass: HomeAssistant, value, expected) -> None:
|
|
"""Test is datetime."""
|
|
assert render(hass, "{{ value is datetime }}", {"value": value}) == expected
|
|
|
|
|
|
def test_strptime(hass: HomeAssistant) -> None:
|
|
"""Test the parse timestamp method."""
|
|
tests = [
|
|
("2016-10-19 15:22:05.588122 UTC", "%Y-%m-%d %H:%M:%S.%f %Z", None),
|
|
("2016-10-19 15:22:05.588122+0100", "%Y-%m-%d %H:%M:%S.%f%z", None),
|
|
("2016-10-19 15:22:05.588122", "%Y-%m-%d %H:%M:%S.%f", None),
|
|
("2016-10-19", "%Y-%m-%d", None),
|
|
("2016", "%Y", None),
|
|
("15:22:05", "%H:%M:%S", None),
|
|
]
|
|
|
|
for inp, fmt, expected in tests:
|
|
if expected is None:
|
|
expected = str(datetime.strptime(inp, fmt))
|
|
|
|
temp = f"{{{{ strptime('{inp}', '{fmt}') }}}}"
|
|
|
|
assert render(hass, temp) == expected
|
|
|
|
# Test handling of invalid input
|
|
invalid_tests = [
|
|
("1469119144", "%Y"),
|
|
("invalid", "%Y"),
|
|
]
|
|
|
|
for inp, fmt in invalid_tests:
|
|
temp = f"{{{{ strptime('{inp}', '{fmt}') }}}}"
|
|
|
|
with pytest.raises(TemplateError):
|
|
render(hass, temp)
|
|
|
|
# Test handling of default return value
|
|
assert render(hass, "{{ strptime('invalid', '%Y', 1) }}") == 1
|
|
assert render(hass, "{{ strptime('invalid', '%Y', default=1) }}") == 1
|
|
|
|
|
|
async def test_timestamp_custom(hass: HomeAssistant) -> None:
|
|
"""Test the timestamps to custom filter."""
|
|
await hass.config.async_set_time_zone("UTC")
|
|
now = dt_util.utcnow()
|
|
tests = [
|
|
(1469119144, None, True, "2016-07-21 16:39:04"),
|
|
(1469119144, "%Y", True, 2016),
|
|
(1469119144, "invalid", True, "invalid"),
|
|
(dt_util.as_timestamp(now), None, False, now.strftime("%Y-%m-%d %H:%M:%S")),
|
|
]
|
|
|
|
for inp, fmt, local, out in tests:
|
|
if fmt:
|
|
fil = f"timestamp_custom('{fmt}')"
|
|
elif fmt and local:
|
|
fil = f"timestamp_custom('{fmt}', {local})"
|
|
else:
|
|
fil = "timestamp_custom"
|
|
|
|
assert render(hass, f"{{{{ {inp} | {fil} }}}}") == out
|
|
|
|
# Test handling of invalid input
|
|
invalid_tests = [
|
|
(None, None, None),
|
|
]
|
|
|
|
for inp, fmt, local in invalid_tests:
|
|
if fmt:
|
|
fil = f"timestamp_custom('{fmt}')"
|
|
elif fmt and local:
|
|
fil = f"timestamp_custom('{fmt}', {local})"
|
|
else:
|
|
fil = "timestamp_custom"
|
|
|
|
with pytest.raises(TemplateError):
|
|
render(hass, f"{{{{ {inp} | {fil} }}}}")
|
|
|
|
# Test handling of default return value
|
|
assert render(hass, "{{ None | timestamp_custom('invalid', True, 1) }}") == 1
|
|
assert render(hass, "{{ None | timestamp_custom(default=1) }}") == 1
|
|
|
|
|
|
async def test_timestamp_local(hass: HomeAssistant) -> None:
|
|
"""Test the timestamps to local filter."""
|
|
await hass.config.async_set_time_zone("UTC")
|
|
tests = [
|
|
(1469119144, "2016-07-21T16:39:04+00:00"),
|
|
]
|
|
|
|
for inp, out in tests:
|
|
assert render(hass, f"{{{{ {inp} | timestamp_local }}}}") == out
|
|
|
|
# Test handling of invalid input
|
|
invalid_tests = [
|
|
None,
|
|
]
|
|
|
|
for inp in invalid_tests:
|
|
with pytest.raises(TemplateError):
|
|
render(hass, f"{{{{ {inp} | timestamp_local }}}}")
|
|
|
|
# Test handling of default return value
|
|
assert render(hass, "{{ None | timestamp_local(1) }}") == 1
|
|
assert render(hass, "{{ None | timestamp_local(default=1) }}") == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"input",
|
|
[
|
|
"2021-06-03 13:00:00.000000+00:00",
|
|
"1986-07-09T12:00:00Z",
|
|
"2016-10-19 15:22:05.588122+0100",
|
|
"2016-10-19",
|
|
"2021-01-01 00:00:01",
|
|
"invalid",
|
|
],
|
|
)
|
|
def test_as_datetime(hass: HomeAssistant, input) -> None:
|
|
"""Test converting a timestamp string to a date object."""
|
|
expected = dt_util.parse_datetime(input)
|
|
if expected is not None:
|
|
expected = str(expected)
|
|
assert render(hass, f"{{{{ as_datetime('{input}') }}}}") == expected
|
|
assert render(hass, f"{{{{ '{input}' | as_datetime }}}}") == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("input", "output"),
|
|
[
|
|
(1469119144, "2016-07-21 16:39:04+00:00"),
|
|
(1469119144.0, "2016-07-21 16:39:04+00:00"),
|
|
(-1, "1969-12-31 23:59:59+00:00"),
|
|
],
|
|
)
|
|
def test_as_datetime_from_timestamp(
|
|
hass: HomeAssistant,
|
|
input: float,
|
|
output: str,
|
|
) -> None:
|
|
"""Test converting a UNIX timestamp to a date object."""
|
|
assert render(hass, f"{{{{ as_datetime({input}) }}}}") == output
|
|
assert render(hass, f"{{{{ {input} | as_datetime }}}}") == output
|
|
assert render(hass, f"{{{{ as_datetime('{input}') }}}}") == output
|
|
assert render(hass, f"{{{{ '{input}' | as_datetime }}}}") == output
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("input", "output"),
|
|
[
|
|
(
|
|
"{% set dt = as_datetime('2024-01-01 16:00:00-08:00') %}",
|
|
"2024-01-01 16:00:00-08:00",
|
|
),
|
|
(
|
|
"{% set dt = as_datetime('2024-01-29').date() %}",
|
|
"2024-01-29 00:00:00",
|
|
),
|
|
],
|
|
)
|
|
def test_as_datetime_from_datetime(
|
|
hass: HomeAssistant, input: str, output: str
|
|
) -> None:
|
|
"""Test using datetime.datetime or datetime.date objects as input."""
|
|
|
|
assert render(hass, f"{input}{{{{ dt | as_datetime }}}}") == output
|
|
|
|
assert render(hass, f"{input}{{{{ as_datetime(dt) }}}}") == output
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("input", "default", "output"),
|
|
[
|
|
(1469119144, 123, "2016-07-21 16:39:04+00:00"),
|
|
('"invalid"', ["default output"], ["default output"]),
|
|
(["a", "list"], 0, 0),
|
|
({"a": "dict"}, None, None),
|
|
],
|
|
)
|
|
def test_as_datetime_default(
|
|
hass: HomeAssistant, input: Any, default: Any, output: str
|
|
) -> None:
|
|
"""Test invalid input and return default value."""
|
|
|
|
assert render(hass, f"{{{{ as_datetime({input}, default={default}) }}}}") == output
|
|
assert render(hass, f"{{{{ {input} | as_datetime({default}) }}}}") == output
|
|
|
|
|
|
def test_as_local(hass: HomeAssistant) -> None:
|
|
"""Test converting time to local."""
|
|
|
|
hass.states.async_set("test.object", "available")
|
|
last_updated = hass.states.get("test.object").last_updated
|
|
assert render(hass, "{{ as_local(states.test.object.last_updated) }}") == str(
|
|
dt_util.as_local(last_updated)
|
|
)
|
|
assert render(hass, "{{ states.test.object.last_updated | as_local }}") == str(
|
|
dt_util.as_local(last_updated)
|
|
)
|
|
|
|
|
|
def test_timestamp_utc(hass: HomeAssistant) -> None:
|
|
"""Test the timestamps to local filter."""
|
|
now = dt_util.utcnow()
|
|
tests = [
|
|
(1469119144, "2016-07-21T16:39:04+00:00"),
|
|
(dt_util.as_timestamp(now), now.isoformat()),
|
|
]
|
|
|
|
for inp, out in tests:
|
|
assert render(hass, f"{{{{ {inp} | timestamp_utc }}}}") == out
|
|
|
|
# Test handling of invalid input
|
|
invalid_tests = [
|
|
None,
|
|
]
|
|
|
|
for inp in invalid_tests:
|
|
with pytest.raises(TemplateError):
|
|
render(hass, f"{{{{ {inp} | timestamp_utc }}}}")
|
|
|
|
# Test handling of default return value
|
|
assert render(hass, "{{ None | timestamp_utc(1) }}") == 1
|
|
assert render(hass, "{{ None | timestamp_utc(default=1) }}") == 1
|
|
|
|
|
|
def test_as_timestamp(hass: HomeAssistant) -> None:
|
|
"""Test the as_timestamp function."""
|
|
with pytest.raises(TemplateError):
|
|
render(hass, '{{ as_timestamp("invalid") }}')
|
|
|
|
hass.states.async_set("test.object", None)
|
|
with pytest.raises(TemplateError):
|
|
render(hass, "{{ as_timestamp(states.test.object) }}")
|
|
|
|
tpl = (
|
|
'{{ as_timestamp(strptime("2024-02-03T09:10:24+0000", '
|
|
'"%Y-%m-%dT%H:%M:%S%z")) }}'
|
|
)
|
|
assert render(hass, tpl) == 1706951424.0
|
|
|
|
# Test handling of default return value
|
|
assert render(hass, "{{ 'invalid' | as_timestamp(1) }}") == 1
|
|
assert render(hass, "{{ 'invalid' | as_timestamp(default=1) }}") == 1
|
|
assert render(hass, "{{ as_timestamp('invalid', 1) }}") == 1
|
|
assert render(hass, "{{ as_timestamp('invalid', default=1) }}") == 1
|
|
|
|
|
|
def test_as_timedelta(hass: HomeAssistant) -> None:
|
|
"""Test the as_timedelta function/filter."""
|
|
|
|
result = render(hass, "{{ as_timedelta('PT10M') }}")
|
|
assert result == "0:10:00"
|
|
|
|
result = render(hass, "{{ 'PT10M' | as_timedelta }}")
|
|
assert result == "0:10:00"
|
|
|
|
result = render(hass, "{{ 'T10M' | as_timedelta }}")
|
|
assert result is None
|
|
|
|
|
|
@patch(
|
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
|
return_value=True,
|
|
)
|
|
def test_now(mock_is_safe, hass: HomeAssistant) -> None:
|
|
"""Test now method."""
|
|
now = dt_util.now()
|
|
with freeze_time(now):
|
|
info = render_to_info(hass, "{{ now().isoformat() }}")
|
|
assert now.isoformat() == info.result()
|
|
|
|
assert info.has_time is True
|
|
|
|
|
|
@patch(
|
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
|
return_value=True,
|
|
)
|
|
def test_utcnow(mock_is_safe, hass: HomeAssistant) -> None:
|
|
"""Test now method."""
|
|
utcnow = dt_util.utcnow()
|
|
with freeze_time(utcnow):
|
|
info = render_to_info(hass, "{{ utcnow().isoformat() }}")
|
|
assert utcnow.isoformat() == info.result()
|
|
|
|
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,
|
|
)
|
|
async def test_today_at(
|
|
mock_is_safe, hass: HomeAssistant, now, expected, expected_midnight, timezone_str
|
|
) -> None:
|
|
"""Test today_at method."""
|
|
freezer = freeze_time(now)
|
|
freezer.start()
|
|
|
|
await hass.config.async_set_time_zone(timezone_str)
|
|
|
|
result = render(hass, "{{ today_at('10:00').isoformat() }}")
|
|
assert result == expected
|
|
|
|
result = render(hass, "{{ today_at('10:00:00').isoformat() }}")
|
|
assert result == expected
|
|
|
|
result = render(hass, "{{ ('10:00:00' | today_at).isoformat() }}")
|
|
assert result == expected
|
|
|
|
result = render(hass, "{{ today_at().isoformat() }}")
|
|
assert result == expected_midnight
|
|
|
|
with pytest.raises(TemplateError):
|
|
render(hass, "{{ today_at('bad') }}")
|
|
|
|
info = render_to_info(hass, "{{ today_at('10:00').isoformat() }}")
|
|
assert info.has_time is True
|
|
|
|
freezer.stop()
|
|
|
|
|
|
@patch(
|
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
|
return_value=True,
|
|
)
|
|
async def test_relative_time(mock_is_safe, hass: HomeAssistant) -> None:
|
|
"""Test relative_time method."""
|
|
await hass.config.async_set_time_zone("UTC")
|
|
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
relative_time_template = (
|
|
'{{relative_time(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}'
|
|
)
|
|
with freeze_time(now):
|
|
result = render(hass, relative_time_template)
|
|
assert result == "1 hour"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" relative_time("
|
|
" strptime("
|
|
' "2000-01-01 09:00:00 +01:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2 hours"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" relative_time("
|
|
" strptime("
|
|
' "2000-01-01 03:00:00 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour"
|
|
|
|
result1 = str(
|
|
datetime.strptime("2000-01-01 11:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
)
|
|
result2 = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" relative_time("
|
|
" strptime("
|
|
' "2000-01-01 11:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result1 == result2
|
|
|
|
result = render(hass, '{{relative_time("string")}}')
|
|
assert result == "string"
|
|
|
|
# Test behavior when current time is same as the input time
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" relative_time("
|
|
" strptime("
|
|
' "2000-01-01 10:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "0 seconds"
|
|
|
|
# Test behavior when the input time is in the future
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" relative_time("
|
|
" strptime("
|
|
' "2000-01-01 11:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2000-01-01 11:00:00+00:00"
|
|
|
|
info = render_to_info(hass, relative_time_template)
|
|
assert info.has_time is True
|
|
|
|
|
|
@patch(
|
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
|
return_value=True,
|
|
)
|
|
async def test_time_since(mock_is_safe, hass: HomeAssistant) -> None:
|
|
"""Test time_since method."""
|
|
await hass.config.async_set_time_zone("UTC")
|
|
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
time_since_template = (
|
|
'{{time_since(strptime("2000-01-01 09:00:00", "%Y-%m-%d %H:%M:%S"))}}'
|
|
)
|
|
with freeze_time(now):
|
|
result = render(hass, time_since_template)
|
|
assert result == "1 hour"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 09:00:00 +01:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2 hours"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 03:00:00 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour"
|
|
|
|
result1 = str(
|
|
datetime.strptime("2000-01-01 11:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
)
|
|
result2 = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 11:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 2"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result1 == result2
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 09:05:00 +01:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision=2"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour 55 minutes"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 02:05:27 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 3"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour 54 minutes 33 seconds"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 02:05:27 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z")'
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2 hours"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "1999-02-01 02:05:27 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 0"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "11 months 4 days 1 hour 54 minutes 33 seconds"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "1999-02-01 02:05:27 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z")'
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "11 months"
|
|
result1 = str(
|
|
datetime.strptime("2000-01-01 11:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
)
|
|
result2 = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_since("
|
|
" strptime("
|
|
' "2000-01-01 11:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision=3"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result1 == result2
|
|
|
|
result = render(hass, '{{time_since("string")}}')
|
|
assert result == "string"
|
|
|
|
info = render_to_info(hass, time_since_template)
|
|
assert info.has_time is True
|
|
|
|
|
|
@patch(
|
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
|
return_value=True,
|
|
)
|
|
async def test_time_until(mock_is_safe, hass: HomeAssistant) -> None:
|
|
"""Test time_until method."""
|
|
await hass.config.async_set_time_zone("UTC")
|
|
now = datetime.strptime("2000-01-01 10:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
time_until_template = (
|
|
'{{time_until(strptime("2000-01-01 11:00:00", "%Y-%m-%d %H:%M:%S"))}}'
|
|
)
|
|
with freeze_time(now):
|
|
result = render(hass, time_until_template)
|
|
assert result == "1 hour"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 13:00:00 +01:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2 hours"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 05:00:00 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"'
|
|
" )"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour"
|
|
|
|
result1 = str(
|
|
datetime.strptime("2000-01-01 09:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
)
|
|
result2 = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 09:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 2"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result1 == result2
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 12:05:00 +01:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision=2"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour 5 minutes"
|
|
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 05:54:33 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 3"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 hour 54 minutes 33 seconds"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 05:54:33 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z")'
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "2 hours"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2001-02-01 05:54:33 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 0"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 year 1 month 2 days 1 hour 54 minutes 33 seconds"
|
|
result = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2001-02-01 05:54:33 -06:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision = 4"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result == "1 year 1 month 2 days 2 hours"
|
|
result1 = str(
|
|
datetime.strptime("2000-01-01 09:00:00 +00:00", "%Y-%m-%d %H:%M:%S %z")
|
|
)
|
|
result2 = render(
|
|
hass,
|
|
(
|
|
"{{"
|
|
" time_until("
|
|
" strptime("
|
|
' "2000-01-01 09:00:00 +00:00",'
|
|
' "%Y-%m-%d %H:%M:%S %z"),'
|
|
" precision=3"
|
|
" )"
|
|
"}}"
|
|
),
|
|
)
|
|
assert result1 == result2
|
|
|
|
result = render(hass, '{{time_until("string")}}')
|
|
assert result == "string"
|
|
|
|
info = render_to_info(hass, time_until_template)
|
|
assert info.has_time is True
|