Don't raise errors when using datetime objects in as_datetime Jinja function/filter (#109062)

* add support for datetime objects to as_datetime

* change import of datetime.date

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Martijn van der Pol 2024-04-23 09:55:58 +02:00 committed by GitHub
parent 3d59303433
commit e90d76b18d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 4 deletions

View File

@ -9,7 +9,7 @@ import collections.abc
from collections.abc import Callable, Generator, Iterable
from contextlib import AbstractContextManager, suppress
from contextvars import ContextVar
from datetime import datetime, timedelta
from datetime import date, datetime, time, timedelta
from functools import cache, lru_cache, partial, wraps
import json
import logging
@ -2001,12 +2001,12 @@ def square_root(value, default=_SENTINEL):
def timestamp_custom(value, date_format=DATE_STR_FORMAT, local=True, default=_SENTINEL):
"""Filter to convert given timestamp to format."""
try:
date = dt_util.utc_from_timestamp(value)
result = dt_util.utc_from_timestamp(value)
if local:
date = dt_util.as_local(date)
result = dt_util.as_local(result)
return date.strftime(date_format)
return result.strftime(date_format)
except (ValueError, TypeError):
# If timestamp can't be converted
if default is _SENTINEL:
@ -2048,6 +2048,12 @@ def forgiving_as_timestamp(value, default=_SENTINEL):
def as_datetime(value: Any, default: Any = _SENTINEL) -> Any:
"""Filter and to convert a time string or UNIX timestamp to datetime object."""
# Return datetime.datetime object without changes
if type(value) is datetime:
return value
# Add midnight to datetime.date object
if type(value) is date:
return datetime.combine(value, time(0, 0, 0))
try:
# Check for a valid UNIX timestamp string, int or float
timestamp = float(value)

View File

@ -1198,6 +1198,35 @@ def test_as_datetime_from_timestamp(
)
@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 (
template.Template(f"{input}{{{{ dt | as_datetime }}}}", hass).async_render()
== output
)
assert (
template.Template(f"{input}{{{{ as_datetime(dt) }}}}", hass).async_render()
== output
)
@pytest.mark.parametrize(
("input", "default", "output"),
[