-
-
Notifications
You must be signed in to change notification settings - Fork 33.9k
Deprecate relative_time in favor of time_since and time_until #86136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
future
and depth
support to the relative_time
template function
@rlippmann Please improve the PR description to give some background and motivation to why this is useful. Also, is a numerical |
Updated |
Should I close this? |
This functionality would be great - I'm trying to create some local calendar reminders, and need things like |
Well, I’m not sure how to get this merged. Or why it’s been sitting here for months… @frenck can you advise? |
@haydndup maybe if you reviewed this it could finally get merged…. |
@rlippmann, I reviewed and approved the changes and it looks good to me. I'm not an approving reviewer, so would still need additional approvals from the HA team. I left some minor suggestions in home-assistant/home-assistant.io#25631. |
Thanks! Now if only I can find an approving reviewer to approve, lol. This would make life so much easier for writing templates for timers. |
Please do not merge |
I would find the feature very useful as well. |
homeassistant/helpers/template.py
Outdated
@@ -2095,15 +2095,23 @@ def today_at(hass: HomeAssistant, time_str: str = "") -> datetime: | |||
return datetime.combine(today, time_today, today.tzinfo) | |||
|
|||
|
|||
def relative_time(hass: HomeAssistant, value: Any) -> Any: | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please remove this extra line#2098 this should fix your black failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it doesn’t appear that this patch will be approved, so I haven’t bothered.
But I made the change anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @rlippmann, I'm still following this issue and hoping it will be merged! Maybe @disforw can advise on next steps?
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
Who can approve this? Can't believe that such a simple change is literally taking months. |
@haydndup Me neither. I've pretty much given up hope that it will every be merged. And I haven't rebased this in months. |
I got nothing. Epenet is the one you want.. |
homeassistant/helpers/template.py
Outdated
@@ -2095,15 +2095,22 @@ def today_at(hass: HomeAssistant, time_str: str = "") -> datetime: | |||
return datetime.combine(today, time_today, today.tzinfo) | |||
|
|||
|
|||
def relative_time(hass: HomeAssistant, value: Any) -> Any: | |||
def relative_time( | |||
hass: HomeAssistant, value: Any | datetime, is_future: bool = False, depth: int = 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_future
is not a good name since the caller does not know if the passed time is in the future or in the past, can we come up with something better? Maybe name it remaining_time
, time_until
, elapsed_time
or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allow_future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's not good.
We're not allowing or not allowing the timestamp to be in the future, we're either calculating time elapsed since some time in the past or we're calculating remaining time until some time in the future.
homeassistant/util/dt.py
Outdated
@@ -267,36 +267,61 @@ def parse_time(time_str: str) -> dt.time | None: | |||
return None | |||
|
|||
|
|||
def get_age(date: dt.datetime) -> str: | |||
def get_age(date: dt.datetime, is_future: bool = False, depth: int = 1) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the name of the function, it seems very unnatural to add a parameter is_future
to it; I would expect it to return a negative age for a time in the future.
Maybe split this up in multiple functions:
- get_age, which returns the time elapsed since a time in the past
- a new function, maybe named something like
get_remaining_time
which returns the remaining time to a time in the future - A helper functions which formats the time delta calculated by
get_age
and the new function as a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about:
- Rename this to
get_diff()
- Change
is_future
to an enum, with values likeDiffType.PAST_ONLY
,DiffType.FUTURE_ONLY
,DiffType.ANY
-- this makes the code much easier to read than trying to figure out what a bool means in this context - Re-add
get_age
for backwards-compat that just callsget_diff(date, DiffType.PAST_ONLY, 1)
Note: There may not be value in having ANY
, but being an enum at least opens this possibility. (I feel like I've needed a way to do a past-or-future date before, but I'm struggling to think of a good use case now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your suggestion is fine 👍
There may not be value in having ANY, but being an enum at least opens this possibility.
Let's not add functionality which we are not sure is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been a while, but I think the is_future was meant to be more like an "allow future" flag.
An enum with 2 values is a boolean :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but then please come up with a good name for a bool which clearly communicates how the behavior changes. I don't think allow_future
is good because it's not clear setting it to True
means a time in the past is no longer allowed.
Hence my proposal to leave the behavior of get_age
unchanged and add a new function get_remaining_time
which returns remaining time until some time in the future.
Please mark the PR as ready for review once the changes have been implemented. |
…ant#105327) * Work-a-round orjson for `to_json` fiter in case dict key is str subclass * Add option instead * Remove json.dumps work-a-round * Update homeassistant/helpers/template.py * Fix test --------- Co-authored-by: Erik Montnemery <erik@montnemery.com>
Oops, i made a little mess on the rebase. |
Yeah, I think you should do both:
|
This was standard practice in our old template functions, but we now prefer raising unless a default value is provided by the user. I think we should do that too here.
I'd say just raise in that case since the function is used incorrectly?
The existing code takes the easy route and assumes a month is 30 days. If we want to change that, we should do that in a separate PR, I think. There's a 3rd party library which supports calculations with calendar months: https://dateutil.readthedocs.io/en/stable/relativedelta.html
I think the current behavior of @MartinHjelmare Maybe you can comment too? |
Sounds reasonable.
Currently precision = 0 returns maximum precision. I don't think that's an unreasonable action, but I can change it to raise if that's better.
That's what I was thinking too.
Actually, the current behavior returns the object. For time_until, I think returning 0 is a reasonable action since its use case would be for a countdown timer. I'm not sure if that's a good action for time_since.
|
I'm not sure what you mean by this. Can you point me to a section in the code where this is already done? |
Search the code base for Your warning function should do something like this: from homeassistant.core import DOMAIN as HA_DOMAIN
import homeassistant.helpers.issue_registry as ir
def _warn_relative_time_deprecated(hass: HomeAssistant) -> None:
issue_registry = ir.async_get_issue_registry(self.hass)
issue_id = "template_function_relative_time_deprecated"
if issue_registry.async_get_issue(HA_DOMAIN, issue_id):
return
ir.async_create_issue(
hass,
HA_DOMAIN,
issue_id,
breaks_in_ha_version="2024.6.0",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key=issue_id,
)
_LOGGER.warning("blablabla") The translation for the issue should be added in |
I'm setting this as draft, please mark as ready for review when the deprecation warning etc. are implemented. |
OK, I agree that makes sense 👍
I see. That behavior seems odd for |
Please update the PR title and PR description:
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
Bump |
Proposed change
Add
future
anddepth
support to therelative_time
template function:with these changes, an end user can simply do:
relative_time(sensor.timer_name,future=true, depth = whatever) to create a human readable version of time remaining
currently to do this the user needs to deal with datetime objects and strptime and then chop up the resulting string.
Type of change
Additional information
Checklist
black --fast homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
..coveragerc
.To help with the load of incoming pull requests: