""" Setup for Tuya datetime entities """ import logging import time from datetime import datetime, timedelta, timezone from homeassistant.components.datetime import DateTimeEntity from .device import TuyaLocalDevice from .entity import TuyaLocalEntity from .helpers.config import async_tuya_setup_platform from .helpers.device_config import TuyaEntityConfig _LOGGER = logging.getLogger(__name__) EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc) async def async_setup_entry(hass, config_entry, async_add_entities): config = {**config_entry.data, **config_entry.options} await async_tuya_setup_platform( hass, async_add_entities, config, "datetime", TuyaLocalDateTime, ) class TuyaLocalDateTime(TuyaLocalEntity, DateTimeEntity): """Representation of a Tuya DateTime""" def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig): """ Initialise the datetime entity. Args: device (TuyaLocalDevice): the device API instance config (TuyaEntityConfig): the configuration for this entity """ super().__init__() dps_map = self._init_begin(device, config) self._year_dps = dps_map.pop("year", None) self._month_dps = dps_map.pop("month", None) self._day_dps = dps_map.pop("day", None) self._hour_dps = dps_map.pop("hour", None) self._minute_dps = dps_map.pop("minute", None) self._second_dps = dps_map.pop("second", None) if ( self._year_dps is None and self._month_dps is None and self._day_dps is None and self._hour_dps is None and self._minute_dps is None and self._second_dps is None ): raise AttributeError( f"{config.config_id} is missing an hour, minute or second dp" ) self._init_end(dps_map) @property def native_value(self): """Return the current value of the time.""" year = month = day = hours = minutes = seconds = None tz = timezone.utc if self._year_dps: year = self._year_dps.get_value(self._device) tz = time.now().astimezone().tzinfo if self._month_dps: month = self._month_dps.get_value(self._device) if self._day_dps: day = self._day_dps.get_value(self._device) if self._hour_dps: hours = self._hour_dps.get_value(self._device) if self._minute_dps: minutes = self._minute_dps.get_value(self._device) if self._second_dps: seconds = self._second_dps.get_value(self._device) if ( year is None and month is None and day is None and hours is None and minutes is None and seconds is None ): return None year = year or 1970 month = month or 1 days = (day or 1) - 1 hours = hours or 0 minutes = minutes or 0 seconds = seconds or 0 delta = timedelta( days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds), ) return datetime(year=year, month=month, day=1, tzinfo=tz) + delta async def async_set_value(self, value: datetime): """Set the datetime.""" settings = {} # Use Local time if split into components if self._year_dps: tz = time.now().astimezone().tzinfo value = value.astimezone(tz) year = value.year month = value.month day = value.day hour = value.hour minute = value.minute second = value.second if self._year_dps: settings.update( self._year_dps.get_values_to_set(self._device, year, settings) ) month = month + (year - 1970) * 12 if self._month_dps: settings.update( self._month_dps.get_values_to_set(self._device, month, settings) ) else: if self._year_dps is None: from_year = 1970 else: from_year = value.year day = ( day + ( datetime(value.year, value.month, 1) - datetime(from_year, 1, 1) ).days - 1 ) if self._day_dps: settings.update( self._day_dps.get_values_to_set(self._device, day, settings) ) else: hour = hour + day * 24 if self._hour_dps: settings.update( self._hour_dps.get_values_to_set(self._device, hour, settings) ) else: minute = minute + hour * 60 if self._minute_dps: settings.update( self._minute_dps.get_values_to_set(self._device, minute, settings) ) else: second = second + minute * 60 if self._second_dps: settings.update( self._second_dps.get_values_to_set(self._device, second, settings) ) else: _LOGGER.debug( "%s: Discarding unused precision: %d seconds", self.name, second, ) await self._device.async_set_properties(settings)