From 2a8f623d7a81b211f540d36ce534ba385fa78b2c Mon Sep 17 00:00:00 2001 From: Jenny Date: Thu, 8 Jul 2021 19:22:30 +0100 Subject: [PATCH] Adds option to Count up from a date (#104) * Add option to count up * Update sensor.py * update docs --- README.md | 3 ++- custom_components/anniversaries/config_flow.py | 11 +++++++++++ custom_components/anniversaries/const.py | 4 ++++ custom_components/anniversaries/sensor.py | 11 +++++++++-- custom_components/anniversaries/translations/en.json | 2 ++ info.md | 3 ++- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7210bc9..a38468b 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ anniversaries: | `name` | No | Friendly name |`date` | Either `date` or `date_template` MUST be included | date in format `'YYYY-MM-DD'` (or `'MM-DD'` if year is unknown) |`date_template` | Either `date` or `date_template` MUST be included | Template to evaluate date from _(Note this is ONLY available in YAML configuration)_ The template must return a string in either `'YYYY-MM-DD'` or `'MM-DD'` format +| `count_up` | Yes | `true` or `false` changes the state to count up from a date (can be useful for non-recurring events) **Default**: `false` | `one_time` | Yes | `true` or `false`. For a one-time event (Non-recurring) **Default**: `false` | `show_half_anniversary` | Yes | `true` or `false`. Enables the `half_anniversary_date` and `days_until_half_anniversary` attributes. **Default**: `false` | `date_format` | Yes | formats the returned date **Default**: '%Y-%m-%d' _for reference, see [http://strftime.org/](http://strftime.org/)_ @@ -89,7 +90,7 @@ anniversaries: ### State -* The number of days remaining to the next occurance. +* The number of days remaining to the next occurance. (or days since last occurence if you have chosen the count up option) ### Attributes diff --git a/custom_components/anniversaries/config_flow.py b/custom_components/anniversaries/config_flow.py index eec34b7..4f997d1 100644 --- a/custom_components/anniversaries/config_flow.py +++ b/custom_components/anniversaries/config_flow.py @@ -7,6 +7,7 @@ import uuid from .const import ( + DEFAULT_COUNT_UP, DOMAIN, DEFAULT_ICON_NORMAL, DEFAULT_ICON_SOON, @@ -17,6 +18,7 @@ DEFAULT_UNIT_OF_MEASUREMENT, DEFAULT_ID_PREFIX, DEFAULT_ONE_TIME, + DEFAULT_COUNT_UP, CONF_ICON_NORMAL, CONF_ICON_TODAY, CONF_ICON_SOON, @@ -27,6 +29,7 @@ CONF_UNIT_OF_MEASUREMENT, CONF_ID_PREFIX, CONF_ONE_TIME, + CONF_COUNT_UP, ) from homeassistant.const import CONF_NAME @@ -62,6 +65,7 @@ async def async_step_icons(self, user_input=None): async def _show_user_form(self, user_input): name = "" date = "" + count_up = DEFAULT_COUNT_UP one_time = DEFAULT_ONE_TIME half_anniversary = DEFAULT_HALF_ANNIVERSARY date_format = DEFAULT_DATE_FORMAT @@ -72,6 +76,8 @@ async def _show_user_form(self, user_input): name = user_input[CONF_NAME] if CONF_DATE in user_input: date = user_input[CONF_DATE] + if CONF_COUNT_UP in user_input: + count_up = user_input[CONF_COUNT_UP] if CONF_ONE_TIME in user_input: one_time = user_input[CONF_ONE_TIME] if CONF_HALF_ANNIVERSARY in user_input: @@ -85,6 +91,7 @@ async def _show_user_form(self, user_input): data_schema = OrderedDict() data_schema[vol.Required(CONF_NAME, default=name)] = str data_schema[vol.Required(CONF_DATE, default=date)] = str + data_schema[vol.Required(CONF_COUNT_UP, default=count_up)] = bool data_schema[vol.Required(CONF_ONE_TIME, default=one_time)] = bool data_schema[vol.Required(CONF_HALF_ANNIVERSARY, default=half_anniversary)] = bool data_schema[vol.Required(CONF_DATE_FORMAT, default=date_format)] = str @@ -172,9 +179,12 @@ async def async_step_icons(self, user_input=None): async def _show_init_form(self, user_input): data_schema = OrderedDict() + count_up = self.config_entry.options.get(CONF_COUNT_UP) one_time = self.config_entry.options.get(CONF_ONE_TIME) unit_of_measurement = self.config_entry.options.get(CONF_UNIT_OF_MEASUREMENT) half_anniversary = self.config_entry.options.get(CONF_HALF_ANNIVERSARY) + if count_up is None: + count_up = DEFAULT_COUNT_UP if one_time is None: one_time = DEFAULT_ONE_TIME if half_anniversary is None: @@ -183,6 +193,7 @@ async def _show_init_form(self, user_input): unit_of_measurement = DEFAULT_UNIT_OF_MEASUREMENT data_schema[vol.Required(CONF_NAME,default=self.config_entry.options.get(CONF_NAME),)] = str data_schema[vol.Required(CONF_DATE, default=self.config_entry.options.get(CONF_DATE),)] = str + data_schema[vol.Required(CONF_COUNT_UP, default=count_up,)] = bool data_schema[vol.Required(CONF_ONE_TIME, default=one_time,)] = bool data_schema[vol.Required(CONF_HALF_ANNIVERSARY,default=half_anniversary,)] = bool data_schema[vol.Required(CONF_DATE_FORMAT,default=self.config_entry.options.get(CONF_DATE_FORMAT),)] = str diff --git a/custom_components/anniversaries/const.py b/custom_components/anniversaries/const.py index 97ca351..c34599d 100644 --- a/custom_components/anniversaries/const.py +++ b/custom_components/anniversaries/const.py @@ -1,4 +1,5 @@ """ Constants """ +from typing import Optional import voluptuous as vol from datetime import datetime import homeassistant.helpers.config_validation as cv @@ -35,6 +36,7 @@ CONF_UNIT_OF_MEASUREMENT = "unit_of_measurement" CONF_ID_PREFIX = "id_prefix" CONF_ONE_TIME = "one_time" +CONF_COUNT_UP = "count_up" CONF_DATE_EXCLUSION_ERROR = "Configuration cannot include both `date` and `date_template`. configure ONLY ONE" CONF_DATE_REQD_ERROR = "Either `date` or `date_template` is Required" @@ -49,6 +51,7 @@ DEFAULT_UNIT_OF_MEASUREMENT = "Days" DEFAULT_ID_PREFIX = "anniversary_" DEFAULT_ONE_TIME = False +DEFAULT_COUNT_UP = False ICON = DEFAULT_ICON_NORMAL @@ -86,6 +89,7 @@ def check_date(value): vol.Optional(CONF_UNIT_OF_MEASUREMENT, default=DEFAULT_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_ID_PREFIX, default=DEFAULT_ID_PREFIX): cv.string, vol.Optional(CONF_ONE_TIME, default=DEFAULT_ONE_TIME): cv.boolean, + vol.Optional(CONF_COUNT_UP, default=DEFAULT_COUNT_UP): cv.boolean, } ) diff --git a/custom_components/anniversaries/sensor.py b/custom_components/anniversaries/sensor.py index 238239e..a14627f 100644 --- a/custom_components/anniversaries/sensor.py +++ b/custom_components/anniversaries/sensor.py @@ -25,6 +25,7 @@ CONF_UNIT_OF_MEASUREMENT, CONF_ID_PREFIX, CONF_ONE_TIME, + CONF_COUNT_UP, ) ATTR_YEARS_NEXT = "years_at_next_anniversary" @@ -88,6 +89,7 @@ def __init__(self, hass, config): if self._unit_of_measurement is None: self._unit_of_measurement = DEFAULT_UNIT_OF_MEASUREMENT self._one_time = config.get(CONF_ONE_TIME) + self._count_up = config.get(CONF_COUNT_UP) @property def unique_id(self): @@ -150,7 +152,7 @@ async def async_update(self): if self._date == "Invalid Date": self._state = self._date return - + today = date.today() years = today.year - self._date.year nextDate = self._date.date() @@ -165,7 +167,7 @@ async def async_update(self): nextDate = self._date.date() + relativedelta(year=today.year + 1) daysRemaining = (nextDate - today).days - + if self._unknown_year: self._date = datetime(nextDate.year, nextDate.month, nextDate.day) @@ -181,6 +183,11 @@ async def async_update(self): self._years_current = years - 1 self._weeks_remaining = int(daysRemaining / 7) + if self._count_up: + if daysRemaining > 0 and not self._one_time: + nextDate = nextDate + relativedelta(years=-1) + self._state = (today - nextDate).days + if self._show_half_anniversary: nextHalfDate = self._half_date.date() if today > nextHalfDate: diff --git a/custom_components/anniversaries/translations/en.json b/custom_components/anniversaries/translations/en.json index 78da12f..a0b0f8e 100644 --- a/custom_components/anniversaries/translations/en.json +++ b/custom_components/anniversaries/translations/en.json @@ -8,6 +8,7 @@ "data": { "name": "Friendly name", "date": "First Date (yyyy-mm-dd) or (mm-dd) if year is unknown", + "count_up": "Count Up (Count down is default)", "one_time": "One Time Event (Non-recurring)", "show_half_anniversary": "Show Half Anniversary Attributes", "date_format": "Date format (see http://strftime.org/)", @@ -38,6 +39,7 @@ "data": { "name": "Friendly name", "date": "First Date (yyyy-mm-dd) or (mm-yy) if year is unknown", + "count_up": "Count Up (Count down is default)", "one_time": "One Time Event (Non-recurring)", "show_half_anniversary": "Show Half Anniversary Attributes", "date_format": "Date format (see http://strftime.org/)", diff --git a/info.md b/info.md index 81dcc12..29f1577 100644 --- a/info.md +++ b/info.md @@ -16,7 +16,7 @@ The 'anniversaries' component is a Home Assistant custom sensor which counts dow State Returned: -* The number of days remaining to the next occurance. +* The number of days remaining to the next occurance. (or days since last occurence if you have chosen the count up option) Attributes: @@ -63,6 +63,7 @@ anniversaries: | `name` | No | Friendly name |`date` | Either `date` or `date_template` MUST be included | date in format `'YYYY-MM-DD'` (or `'MM-DD'` if year is unknown) |`date_template` | Either `date` or `date_template` MUST be included | Template to evaluate date from _(Note this is ONLY available in YAML configuration)_ The template must return a string in either `'YYYY-MM-DD'` or `'MM-DD'` format +| `count_up` | Yes | `true` or `false` changes the state to count up from a date (can be useful for non-recurring events) **Default**: `false` | `one_time` | Yes | `true` or `false`. For a one-time event (Non-recurring) **Default**: `false` | `show_half_anniversary` | Yes | `true` or `false`. Enables the `half_anniversary_date` and `days_until_half_anniversary` attributes. **Default**: `false` | `date_format` | Yes | formats the returned date **Default**: '%Y-%m-%d' _for reference, see [http://strftime.org/](http://strftime.org/)_