Merge pull request #1833 from home-assistant/iso8601
Use standardised datetime format
This commit is contained in:
commit
37a28c799f
32 changed files with 168 additions and 173 deletions
|
@ -24,7 +24,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
def trigger(hass, config, action):
|
||||
"""Listen for state changes based on configuration."""
|
||||
if CONF_AFTER in config:
|
||||
after = dt_util.parse_time_str(config[CONF_AFTER])
|
||||
after = dt_util.parse_time(config[CONF_AFTER])
|
||||
if after is None:
|
||||
_error_time(config[CONF_AFTER], CONF_AFTER)
|
||||
return False
|
||||
|
@ -62,13 +62,13 @@ def if_action(hass, config):
|
|||
return None
|
||||
|
||||
if before is not None:
|
||||
before = dt_util.parse_time_str(before)
|
||||
before = dt_util.parse_time(before)
|
||||
if before is None:
|
||||
_error_time(before, CONF_BEFORE)
|
||||
return None
|
||||
|
||||
if after is not None:
|
||||
after = dt_util.parse_time_str(after)
|
||||
after = dt_util.parse_time(after)
|
||||
if after is None:
|
||||
_error_time(after, CONF_AFTER)
|
||||
return None
|
||||
|
|
|
@ -49,8 +49,7 @@ class VeraBinarySensor(VeraDevice, BinarySensorDevice):
|
|||
last_tripped = self.vera_device.last_trip
|
||||
if last_tripped is not None:
|
||||
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
|
||||
attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str(
|
||||
utc_time)
|
||||
attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
|
||||
else:
|
||||
attr[ATTR_LAST_TRIP_TIME] = None
|
||||
tripped = self.vera_device.is_tripped
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
"""DO NOT MODIFY. Auto-generated by build_frontend script."""
|
||||
VERSION = "91191cb375be56ce689a38edc782875f"
|
||||
VERSION = "b9460e6bbf5549236815d94f1c1c98b9"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
Subproject commit 1ad673ff6f946de2a6358efcdf59667fbc73a05a
|
||||
Subproject commit a21547abfb8d19605850ec4bee48f837d607f736
|
|
@ -182,7 +182,7 @@ def _api_history_period(handler, path_match, data):
|
|||
one_day = timedelta(seconds=86400)
|
||||
|
||||
if date_str:
|
||||
start_date = dt_util.date_str_to_date(date_str)
|
||||
start_date = dt_util.parse_date(date_str)
|
||||
|
||||
if start_date is None:
|
||||
handler.write_json_message("Error parsing JSON", HTTP_BAD_REQUEST)
|
||||
|
|
|
@ -72,8 +72,7 @@ class VeraLight(VeraDevice, Light):
|
|||
last_tripped = self.vera_device.last_trip
|
||||
if last_tripped is not None:
|
||||
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
|
||||
attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str(
|
||||
utc_time)
|
||||
attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
|
||||
else:
|
||||
attr[ATTR_LAST_TRIP_TIME] = None
|
||||
tripped = self.vera_device.is_tripped
|
||||
|
|
|
@ -87,7 +87,7 @@ def _handle_get_logbook(handler, path_match, data):
|
|||
date_str = path_match.group('date')
|
||||
|
||||
if date_str:
|
||||
start_date = dt_util.date_str_to_date(date_str)
|
||||
start_date = dt_util.parse_date(date_str)
|
||||
|
||||
if start_date is None:
|
||||
handler.write_json_message("Error parsing JSON", HTTP_BAD_REQUEST)
|
||||
|
@ -122,7 +122,7 @@ class Entry(object):
|
|||
def as_dict(self):
|
||||
"""Convert entry to a dict to be used within JSON."""
|
||||
return {
|
||||
'when': dt_util.datetime_to_str(self.when),
|
||||
'when': self.when,
|
||||
'name': self.name,
|
||||
'message': self.message,
|
||||
'domain': self.domain,
|
||||
|
|
|
@ -44,12 +44,12 @@ class FileNotificationService(BaseNotificationService):
|
|||
if os.stat(self.filepath).st_size == 0:
|
||||
title = '{} notifications (Log started: {})\n{}\n'.format(
|
||||
kwargs.get(ATTR_TITLE),
|
||||
dt_util.strip_microseconds(dt_util.utcnow()),
|
||||
dt_util.utcnow().isoformat(),
|
||||
'-' * 80)
|
||||
file.write(title)
|
||||
|
||||
if self.add_timestamp == 1:
|
||||
text = '{} {}\n'.format(dt_util.utcnow(), message)
|
||||
text = '{} {}\n'.format(dt_util.utcnow().isoformat(), message)
|
||||
file.write(text)
|
||||
else:
|
||||
text = '{}\n'.format(message)
|
||||
|
|
|
@ -478,7 +478,7 @@ class Recorder(threading.Thread):
|
|||
|
||||
def _adapt_datetime(datetimestamp):
|
||||
"""Turn a datetime into an integer for in the DB."""
|
||||
return dt_util.as_utc(datetimestamp.replace(microsecond=0)).timestamp()
|
||||
return dt_util.as_utc(datetimestamp).timestamp()
|
||||
|
||||
|
||||
def _verify_instance():
|
||||
|
|
|
@ -23,6 +23,8 @@ ATTR_TARGET = 'Destination'
|
|||
ATTR_REMAINING_TIME = 'Remaining time'
|
||||
ICON = 'mdi:bus'
|
||||
|
||||
TIME_STR_FORMAT = "%H:%M"
|
||||
|
||||
# Return cached results if last scan was less then this time ago.
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60)
|
||||
|
||||
|
@ -126,10 +128,10 @@ class PublicTransportData(object):
|
|||
|
||||
try:
|
||||
self.times = [
|
||||
dt_util.datetime_to_time_str(
|
||||
dt_util.as_local(dt_util.utc_from_timestamp(
|
||||
item['from']['departureTimestamp']))
|
||||
)
|
||||
dt_util.as_local(
|
||||
dt_util.utc_from_timestamp(
|
||||
item['from']['departureTimestamp'])).strftime(
|
||||
TIME_STR_FORMAT)
|
||||
for item in connections
|
||||
]
|
||||
self.times.append(
|
||||
|
|
|
@ -131,9 +131,9 @@ class SystemMonitorSensor(Entity):
|
|||
elif self.type == 'ipv6_address':
|
||||
self._state = psutil.net_if_addrs()[self.argument][1][1]
|
||||
elif self.type == 'last_boot':
|
||||
self._state = dt_util.datetime_to_date_str(
|
||||
dt_util.as_local(
|
||||
dt_util.utc_from_timestamp(psutil.boot_time())))
|
||||
self._state = dt_util.as_local(
|
||||
dt_util.utc_from_timestamp(psutil.boot_time())
|
||||
).date().isoformat()
|
||||
elif self.type == 'since_last_boot':
|
||||
self._state = dt_util.utcnow() - dt_util.utc_from_timestamp(
|
||||
psutil.boot_time())
|
||||
|
|
|
@ -19,6 +19,8 @@ OPTION_TYPES = {
|
|||
'time_utc': 'Time (UTC)',
|
||||
}
|
||||
|
||||
TIME_STR_FORMAT = "%H:%M"
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Time and Date sensor."""
|
||||
|
@ -70,9 +72,9 @@ class TimeDateSensor(Entity):
|
|||
def update(self):
|
||||
"""Get the latest data and updates the states."""
|
||||
time_date = dt_util.utcnow()
|
||||
time = dt_util.datetime_to_time_str(dt_util.as_local(time_date))
|
||||
time_utc = dt_util.datetime_to_time_str(time_date)
|
||||
date = dt_util.datetime_to_date_str(dt_util.as_local(time_date))
|
||||
time = dt_util.as_local(time_date).strftime(TIME_STR_FORMAT)
|
||||
time_utc = time_date.strftime(TIME_STR_FORMAT)
|
||||
date = dt_util.as_local(time_date).date().isoformat()
|
||||
|
||||
# Calculate the beat (Swatch Internet Time) time without date.
|
||||
hours, minutes, seconds = time_date.strftime('%H:%M:%S').split(':')
|
||||
|
|
|
@ -65,8 +65,7 @@ class VeraSensor(VeraDevice, Entity):
|
|||
last_tripped = self.vera_device.last_trip
|
||||
if last_tripped is not None:
|
||||
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
|
||||
attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str(
|
||||
utc_time)
|
||||
attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
|
||||
else:
|
||||
attr[ATTR_LAST_TRIP_TIME] = None
|
||||
tripped = self.vera_device.is_tripped
|
||||
|
|
|
@ -12,6 +12,7 @@ from homeassistant.helpers.entity import Entity
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
DEFAULT_NAME = "Worldclock Sensor"
|
||||
ICON = 'mdi:clock'
|
||||
TIME_STR_FORMAT = "%H:%M"
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
@ -59,5 +60,5 @@ class WorldClockSensor(Entity):
|
|||
|
||||
def update(self):
|
||||
"""Get the time and updates the states."""
|
||||
self._state = dt_util.datetime_to_time_str(
|
||||
dt_util.now(time_zone=self._time_zone))
|
||||
self._state = dt_util.now(time_zone=self._time_zone).strftime(
|
||||
TIME_STR_FORMAT)
|
||||
|
|
|
@ -138,10 +138,8 @@ class YrSensor(Entity):
|
|||
|
||||
# Find sensor
|
||||
for time_entry in self._weather.data['product']['time']:
|
||||
valid_from = dt_util.str_to_datetime(
|
||||
time_entry['@from'], "%Y-%m-%dT%H:%M:%SZ")
|
||||
valid_to = dt_util.str_to_datetime(
|
||||
time_entry['@to'], "%Y-%m-%dT%H:%M:%SZ")
|
||||
valid_from = dt_util.parse_datetime(time_entry['@from'])
|
||||
valid_to = dt_util.parse_datetime(time_entry['@to'])
|
||||
|
||||
loc_data = time_entry['location']
|
||||
|
||||
|
@ -204,5 +202,4 @@ class YrData(object):
|
|||
model = self.data['meta']['model']
|
||||
if '@nextrun' not in model:
|
||||
model = model[0]
|
||||
self._nextrun = dt_util.str_to_datetime(model['@nextrun'],
|
||||
"%Y-%m-%dT%H:%M:%SZ")
|
||||
self._nextrun = dt_util.parse_datetime(model['@nextrun'])
|
||||
|
|
|
@ -50,7 +50,7 @@ def next_setting_utc(hass, entity_id=None):
|
|||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.str_to_datetime(
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_SETTING])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
|
@ -72,8 +72,7 @@ def next_rising_utc(hass, entity_id=None):
|
|||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.str_to_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_RISING])
|
||||
return dt_util.parse_datetime(state.attributes[STATE_ATTR_NEXT_RISING])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_RISING does not exist
|
||||
|
@ -150,10 +149,8 @@ class Sun(Entity):
|
|||
def state_attributes(self):
|
||||
"""Return the state attributes of the sun."""
|
||||
return {
|
||||
STATE_ATTR_NEXT_RISING:
|
||||
dt_util.datetime_to_str(self.next_rising),
|
||||
STATE_ATTR_NEXT_SETTING:
|
||||
dt_util.datetime_to_str(self.next_setting),
|
||||
STATE_ATTR_NEXT_RISING: self.next_rising.isoformat(),
|
||||
STATE_ATTR_NEXT_SETTING: self.next_setting.isoformat(),
|
||||
STATE_ATTR_ELEVATION: round(self.solar_elevation, 2)
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ class VeraSwitch(VeraDevice, SwitchDevice):
|
|||
last_tripped = self.vera_device.last_trip
|
||||
if last_tripped is not None:
|
||||
utc_time = dt_util.utc_from_timestamp(int(last_tripped))
|
||||
attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str(
|
||||
utc_time)
|
||||
attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
|
||||
else:
|
||||
attr[ATTR_LAST_TRIP_TIME] = None
|
||||
tripped = self.vera_device.is_tripped
|
||||
|
|
|
@ -156,8 +156,7 @@ class Event(object):
|
|||
self.event_type = event_type
|
||||
self.data = data or {}
|
||||
self.origin = origin
|
||||
self.time_fired = dt_util.strip_microseconds(
|
||||
time_fired or dt_util.utcnow())
|
||||
self.time_fired = time_fired or dt_util.utcnow()
|
||||
|
||||
def as_dict(self):
|
||||
"""Create a dict representation of this Event."""
|
||||
|
@ -165,7 +164,7 @@ class Event(object):
|
|||
'event_type': self.event_type,
|
||||
'data': dict(self.data),
|
||||
'origin': str(self.origin),
|
||||
'time_fired': dt_util.datetime_to_str(self.time_fired),
|
||||
'time_fired': self.time_fired,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -310,15 +309,9 @@ class State(object):
|
|||
self.entity_id = entity_id.lower()
|
||||
self.state = str(state)
|
||||
self.attributes = MappingProxyType(attributes or {})
|
||||
self.last_updated = dt_util.strip_microseconds(
|
||||
last_updated or dt_util.utcnow())
|
||||
self.last_updated = last_updated or dt_util.utcnow()
|
||||
|
||||
# Strip microsecond from last_changed else we cannot guarantee
|
||||
# state == State.from_dict(state.as_dict())
|
||||
# This behavior occurs because to_dict uses datetime_to_str
|
||||
# which does not preserve microseconds
|
||||
self.last_changed = dt_util.strip_microseconds(
|
||||
last_changed or self.last_updated)
|
||||
self.last_changed = last_changed or self.last_updated
|
||||
|
||||
@property
|
||||
def domain(self):
|
||||
|
@ -346,8 +339,8 @@ class State(object):
|
|||
return {'entity_id': self.entity_id,
|
||||
'state': self.state,
|
||||
'attributes': dict(self.attributes),
|
||||
'last_changed': dt_util.datetime_to_str(self.last_changed),
|
||||
'last_updated': dt_util.datetime_to_str(self.last_updated)}
|
||||
'last_changed': self.last_changed,
|
||||
'last_updated': self.last_updated}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, json_dict):
|
||||
|
@ -361,13 +354,13 @@ class State(object):
|
|||
|
||||
last_changed = json_dict.get('last_changed')
|
||||
|
||||
if last_changed:
|
||||
last_changed = dt_util.str_to_datetime(last_changed)
|
||||
if isinstance(last_changed, str):
|
||||
last_changed = dt_util.parse_datetime(last_changed)
|
||||
|
||||
last_updated = json_dict.get('last_updated')
|
||||
|
||||
if last_updated:
|
||||
last_updated = dt_util.str_to_datetime(last_updated)
|
||||
if isinstance(last_updated, str):
|
||||
last_updated = dt_util.parse_datetime(last_updated)
|
||||
|
||||
return cls(json_dict['entity_id'], json_dict['state'],
|
||||
json_dict.get('attributes'), last_changed, last_updated)
|
||||
|
@ -386,7 +379,7 @@ class State(object):
|
|||
|
||||
return "<state {}={}{} @ {}>".format(
|
||||
self.entity_id, self.state, attr,
|
||||
dt_util.datetime_to_local_str(self.last_changed))
|
||||
dt_util.as_local(self.last_changed).isoformat())
|
||||
|
||||
|
||||
class StateMachine(object):
|
||||
|
@ -819,6 +812,6 @@ def create_worker_pool(worker_count=None):
|
|||
|
||||
for start, job in current_jobs:
|
||||
_LOGGER.warning("WorkerPool:Current job from %s: %s",
|
||||
dt_util.datetime_to_local_str(start), job)
|
||||
dt_util.as_local(start).isoformat(), job)
|
||||
|
||||
return util.ThreadPool(job_handler, worker_count, busy_callback)
|
||||
|
|
|
@ -92,9 +92,8 @@ class TrackStates(object):
|
|||
|
||||
def get_changed_since(states, utc_point_in_time):
|
||||
"""Return list of states that have been changed since utc_point_in_time."""
|
||||
point_in_time = dt_util.strip_microseconds(utc_point_in_time)
|
||||
|
||||
return [state for state in states if state.last_updated >= point_in_time]
|
||||
return [state for state in states
|
||||
if state.last_updated >= utc_point_in_time]
|
||||
|
||||
|
||||
def reproduce_state(hass, states, blocking=False):
|
||||
|
|
|
@ -7,6 +7,7 @@ HomeAssistantError will be raised.
|
|||
For more details about the Python API, please refer to the documentation at
|
||||
https://home-assistant.io/developers/python_api/
|
||||
"""
|
||||
from datetime import datetime
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
|
@ -277,7 +278,9 @@ class JSONEncoder(json.JSONEncoder):
|
|||
|
||||
Hand other objects to the original method.
|
||||
"""
|
||||
if hasattr(obj, 'as_dict'):
|
||||
if isinstance(obj, datetime):
|
||||
return obj.isoformat()
|
||||
elif hasattr(obj, 'as_dict'):
|
||||
return obj.as_dict()
|
||||
|
||||
try:
|
||||
|
|
|
@ -12,7 +12,7 @@ import string
|
|||
from functools import wraps
|
||||
from types import MappingProxyType
|
||||
|
||||
from .dt import datetime_to_local_str, utcnow
|
||||
from .dt import as_local, utcnow
|
||||
|
||||
RE_SANITIZE_FILENAME = re.compile(r'(~|\.\.|/|\\)')
|
||||
RE_SANITIZE_PATH = re.compile(r'(~|\.(\.)+)')
|
||||
|
@ -43,7 +43,7 @@ def repr_helper(inp):
|
|||
repr_helper(key)+"="+repr_helper(item) for key, item
|
||||
in inp.items())
|
||||
elif isinstance(inp, datetime):
|
||||
return datetime_to_local_str(inp)
|
||||
return as_local(inp).isoformat()
|
||||
else:
|
||||
return str(inp)
|
||||
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
"""Provides helper methods to handle the time in HA."""
|
||||
import datetime as dt
|
||||
import re
|
||||
|
||||
import pytz
|
||||
|
||||
DATETIME_STR_FORMAT = "%H:%M:%S %d-%m-%Y"
|
||||
DATE_STR_FORMAT = "%Y-%m-%d"
|
||||
TIME_STR_FORMAT = "%H:%M"
|
||||
UTC = DEFAULT_TIME_ZONE = pytz.utc
|
||||
|
||||
|
||||
# Copyright (c) Django Software Foundation and individual contributors.
|
||||
# All rights reserved.
|
||||
# https://github.com/django/django/blob/master/LICENSE
|
||||
DATETIME_RE = re.compile(
|
||||
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
|
||||
r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
|
||||
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
|
||||
r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
|
||||
)
|
||||
|
||||
|
||||
def set_default_time_zone(time_zone):
|
||||
"""Set a default time zone to be used when none is specified."""
|
||||
global DEFAULT_TIME_ZONE # pylint: disable=global-statement
|
||||
|
@ -75,48 +85,39 @@ def start_of_local_day(dt_or_d=None):
|
|||
tzinfo=DEFAULT_TIME_ZONE)
|
||||
|
||||
|
||||
def datetime_to_local_str(dattim):
|
||||
"""Convert datetime to specified time_zone and returns a string."""
|
||||
return datetime_to_str(as_local(dattim))
|
||||
# Copyright (c) Django Software Foundation and individual contributors.
|
||||
# All rights reserved.
|
||||
# https://github.com/django/django/blob/master/LICENSE
|
||||
def parse_datetime(dt_str):
|
||||
"""Parse a string and return a datetime.datetime.
|
||||
|
||||
|
||||
def datetime_to_str(dattim):
|
||||
"""Convert datetime to a string format.
|
||||
|
||||
@rtype : str
|
||||
This function supports time zone offsets. When the input contains one,
|
||||
the output uses a timezone with a fixed offset from UTC.
|
||||
Raises ValueError if the input is well formatted but not a valid datetime.
|
||||
Returns None if the input isn't well formatted.
|
||||
"""
|
||||
return dattim.strftime(DATETIME_STR_FORMAT)
|
||||
|
||||
|
||||
def datetime_to_time_str(dattim):
|
||||
"""Convert datetime to a string containing only the time.
|
||||
|
||||
@rtype : str
|
||||
"""
|
||||
return dattim.strftime(TIME_STR_FORMAT)
|
||||
|
||||
|
||||
def datetime_to_date_str(dattim):
|
||||
"""Convert datetime to a string containing only the date.
|
||||
|
||||
@rtype : str
|
||||
"""
|
||||
return dattim.strftime(DATE_STR_FORMAT)
|
||||
|
||||
|
||||
def str_to_datetime(dt_str, dt_format=DATETIME_STR_FORMAT):
|
||||
"""Convert a string to a UTC datetime object.
|
||||
|
||||
@rtype: datetime
|
||||
"""
|
||||
try:
|
||||
return dt.datetime.strptime(
|
||||
dt_str, dt_format).replace(tzinfo=pytz.utc)
|
||||
except ValueError: # If dt_str did not match our format
|
||||
match = DATETIME_RE.match(dt_str)
|
||||
if not match:
|
||||
return None
|
||||
kws = match.groupdict()
|
||||
if kws['microsecond']:
|
||||
kws['microsecond'] = kws['microsecond'].ljust(6, '0')
|
||||
tzinfo = kws.pop('tzinfo')
|
||||
if tzinfo == 'Z':
|
||||
tzinfo = UTC
|
||||
elif tzinfo is not None:
|
||||
offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
|
||||
offset_hours = int(tzinfo[1:3])
|
||||
offset = dt.timedelta(hours=offset_hours, minutes=offset_mins)
|
||||
if tzinfo[0] == '-':
|
||||
offset = -offset
|
||||
tzinfo = dt.timezone(offset)
|
||||
kws = {k: int(v) for k, v in kws.items() if v is not None}
|
||||
kws['tzinfo'] = tzinfo
|
||||
return dt.datetime(**kws)
|
||||
|
||||
|
||||
def date_str_to_date(dt_str):
|
||||
def parse_date(dt_str):
|
||||
"""Convert a date string to a date object."""
|
||||
try:
|
||||
return dt.datetime.strptime(dt_str, DATE_STR_FORMAT).date()
|
||||
|
@ -124,12 +125,7 @@ def date_str_to_date(dt_str):
|
|||
return None
|
||||
|
||||
|
||||
def strip_microseconds(dattim):
|
||||
"""Return a copy of dattime object but with microsecond set to 0."""
|
||||
return dattim.replace(microsecond=0)
|
||||
|
||||
|
||||
def parse_time_str(time_str):
|
||||
def parse_time(time_str):
|
||||
"""Parse a time string (00:20:00) into Time object.
|
||||
|
||||
Return None if invalid.
|
||||
|
|
|
@ -34,7 +34,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_sunset_trigger(self):
|
||||
"""Test the sunset trigger."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '02:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T02:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC)
|
||||
|
@ -61,7 +61,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_sunrise_trigger(self):
|
||||
"""Test the sunrise trigger."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC)
|
||||
|
@ -88,7 +88,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_sunset_trigger_with_offset(self):
|
||||
"""Test the sunset trigger with offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '02:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T02:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC)
|
||||
|
@ -116,7 +116,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_sunrise_trigger_with_offset(self):
|
||||
"""Test the runrise trigger with offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC)
|
||||
|
@ -144,7 +144,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_if_action_before(self):
|
||||
"""Test if action was before."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
@ -180,7 +180,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_if_action_after(self):
|
||||
"""Test if action was after."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
@ -216,7 +216,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_if_action_before_with_offset(self):
|
||||
"""Test if action was before offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
@ -253,7 +253,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_if_action_after_with_offset(self):
|
||||
"""Test if action was after offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '14:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
@ -290,8 +290,8 @@ class TestAutomationSun(unittest.TestCase):
|
|||
def test_if_action_before_and_after_during(self):
|
||||
"""Test if action was before and after during."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '10:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '15:00:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T10:00:00Z',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T15:00:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
@ -337,7 +337,7 @@ class TestAutomationSun(unittest.TestCase):
|
|||
import pytz
|
||||
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '17:30:00 16-09-2015',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T17:30:00Z',
|
||||
})
|
||||
|
||||
_setup_component(self.hass, automation.DOMAIN, {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import os
|
||||
import unittest
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
import homeassistant.components.notify as notify
|
||||
from homeassistant.components.notify import (
|
||||
|
@ -31,8 +32,11 @@ class TestNotifyFile(unittest.TestCase):
|
|||
}
|
||||
}))
|
||||
|
||||
def test_notify_file(self):
|
||||
@patch('homeassistant.util.dt.utcnow')
|
||||
def test_notify_file(self, mock_utcnow):
|
||||
"""Test the notify file output."""
|
||||
mock_utcnow.return_value = dt_util.as_utc(dt_util.now())
|
||||
|
||||
with tempfile.TemporaryDirectory() as tempdirname:
|
||||
filename = os.path.join(tempdirname, 'notify.txt')
|
||||
message = 'one, two, testing, testing'
|
||||
|
@ -46,7 +50,7 @@ class TestNotifyFile(unittest.TestCase):
|
|||
}))
|
||||
title = '{} notifications (Log started: {})\n{}\n'.format(
|
||||
ATTR_TITLE_DEFAULT,
|
||||
dt_util.strip_microseconds(dt_util.utcnow()),
|
||||
dt_util.utcnow().isoformat(),
|
||||
'-' * 80)
|
||||
|
||||
self.hass.services.call('notify', 'test', {'message': message},
|
||||
|
|
|
@ -68,7 +68,7 @@ class TestComponentHistory(unittest.TestCase):
|
|||
"""Test humanify filter too frequent sensor values."""
|
||||
entity_id = 'sensor.bla'
|
||||
|
||||
pointA = dt_util.strip_microseconds(dt_util.utcnow().replace(minute=2))
|
||||
pointA = dt_util.utcnow().replace(minute=2)
|
||||
pointB = pointA.replace(minute=5)
|
||||
pointC = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
|
||||
|
|
|
@ -66,13 +66,13 @@ class TestMqttEventStream(unittest.TestCase):
|
|||
mock_sub.assert_called_with(self.hass, sub_topic, ANY)
|
||||
|
||||
@patch('homeassistant.components.mqtt.publish')
|
||||
@patch('homeassistant.core.dt_util.datetime_to_str')
|
||||
def test_state_changed_event_sends_message(self, mock_datetime, mock_pub):
|
||||
@patch('homeassistant.core.dt_util.utcnow')
|
||||
def test_state_changed_event_sends_message(self, mock_utcnow, mock_pub):
|
||||
""""Test the sending of a new message if event changed."""
|
||||
now = '00:19:19 11-01-2016'
|
||||
now = dt_util.as_utc(dt_util.now())
|
||||
e_id = 'fake.entity'
|
||||
pub_topic = 'bar'
|
||||
mock_datetime.return_value = now
|
||||
mock_utcnow.return_value = now
|
||||
|
||||
# Add the eventstream component for publishing events
|
||||
self.assertTrue(self.add_eventstream(pub_topic=pub_topic))
|
||||
|
@ -97,11 +97,11 @@ class TestMqttEventStream(unittest.TestCase):
|
|||
event = {}
|
||||
event['event_type'] = EVENT_STATE_CHANGED
|
||||
new_state = {
|
||||
"last_updated": now,
|
||||
"last_updated": now.isoformat(),
|
||||
"state": "on",
|
||||
"entity_id": e_id,
|
||||
"attributes": {},
|
||||
"last_changed": now
|
||||
"last_changed": now.isoformat()
|
||||
}
|
||||
event['event_data'] = {"new_state": new_state, "entity_id": e_id}
|
||||
|
||||
|
|
|
@ -63,4 +63,16 @@ class TestRecorder(unittest.TestCase):
|
|||
db_events = recorder.query_events(
|
||||
'SELECT * FROM events WHERE event_type = ?', (event_type, ))
|
||||
|
||||
self.assertEqual(events, db_events)
|
||||
assert len(events) == 1
|
||||
assert len(db_events) == 1
|
||||
|
||||
event = events[0]
|
||||
db_event = db_events[0]
|
||||
|
||||
assert event.event_type == db_event.event_type
|
||||
assert event.data == db_event.data
|
||||
assert event.origin == db_event.origin
|
||||
|
||||
# Recorder uses SQLite and stores datetimes as integer unix timestamps
|
||||
assert event.time_fired.replace(microsecond=0) == \
|
||||
db_event.time_fired.replace(microsecond=0)
|
||||
|
|
|
@ -128,7 +128,7 @@ class TestEvent(unittest.TestCase):
|
|||
'event_type': event_type,
|
||||
'data': data,
|
||||
'origin': 'LOCAL',
|
||||
'time_fired': dt_util.datetime_to_str(now),
|
||||
'time_fired': now,
|
||||
}
|
||||
self.assertEqual(expected, event.as_dict())
|
||||
|
||||
|
@ -225,13 +225,14 @@ class TestState(unittest.TestCase):
|
|||
|
||||
def test_repr(self):
|
||||
"""Test state.repr."""
|
||||
self.assertEqual("<state happy.happy=on @ 12:00:00 08-12-1984>",
|
||||
self.assertEqual("<state happy.happy=on @ 1984-12-08T12:00:00+00:00>",
|
||||
str(ha.State(
|
||||
"happy.happy", "on",
|
||||
last_changed=datetime(1984, 12, 8, 12, 0, 0))))
|
||||
|
||||
self.assertEqual(
|
||||
"<state happy.happy=on; brightness=144 @ 12:00:00 08-12-1984>",
|
||||
"<state happy.happy=on; brightness=144 @ "
|
||||
"1984-12-08T12:00:00+00:00>",
|
||||
str(ha.State("happy.happy", "on", {"brightness": 144},
|
||||
datetime(1984, 12, 8, 12, 0, 0))))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import homeassistant.bootstrap as bootstrap
|
|||
import homeassistant.remote as remote
|
||||
import homeassistant.components.http as http
|
||||
from homeassistant.const import HTTP_HEADER_HA_AUTH
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import get_test_instance_port, get_test_home_assistant
|
||||
|
||||
|
@ -194,6 +195,9 @@ class TestRemoteMethods(unittest.TestCase):
|
|||
# Default method raises TypeError if non HA object
|
||||
self.assertRaises(TypeError, ha_json_enc.default, 1)
|
||||
|
||||
now = dt_util.utcnow()
|
||||
self.assertEqual(now.isoformat(), ha_json_enc.default(now))
|
||||
|
||||
|
||||
class TestRemoteClasses(unittest.TestCase):
|
||||
"""Test the homeassistant.remote module."""
|
||||
|
|
|
@ -107,31 +107,16 @@ class TestDateUtil(unittest.TestCase):
|
|||
datetime(1986, 7, 9, tzinfo=dt_util.UTC),
|
||||
dt_util.utc_from_timestamp(521251200))
|
||||
|
||||
def test_datetime_to_str(self):
|
||||
"""Test datetime_to_str."""
|
||||
self.assertEqual(
|
||||
"12:00:00 09-07-1986",
|
||||
dt_util.datetime_to_str(datetime(1986, 7, 9, 12, 0, 0)))
|
||||
def test_parse_datetime_converts_correctly(self):
|
||||
"""Test parse_datetime converts strings."""
|
||||
assert \
|
||||
datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC) == \
|
||||
dt_util.parse_datetime("1986-07-09T12:00:00Z")
|
||||
|
||||
def test_datetime_to_local_str(self):
|
||||
"""Test datetime_to_local_str."""
|
||||
self.assertEqual(
|
||||
dt_util.datetime_to_str(dt_util.now()),
|
||||
dt_util.datetime_to_local_str(dt_util.utcnow()))
|
||||
utcnow = dt_util.utcnow()
|
||||
|
||||
def test_str_to_datetime_converts_correctly(self):
|
||||
"""Test str_to_datetime converts strings."""
|
||||
self.assertEqual(
|
||||
datetime(1986, 7, 9, 12, 0, 0, tzinfo=dt_util.UTC),
|
||||
dt_util.str_to_datetime("12:00:00 09-07-1986"))
|
||||
assert utcnow == dt_util.parse_datetime(utcnow.isoformat())
|
||||
|
||||
def test_str_to_datetime_returns_none_for_incorrect_format(self):
|
||||
"""Test str_to_datetime returns None if incorrect format."""
|
||||
self.assertIsNone(dt_util.str_to_datetime("not a datetime string"))
|
||||
|
||||
def test_strip_microseconds(self):
|
||||
"""Test the now method."""
|
||||
test_time = datetime(2015, 1, 1, microsecond=5000)
|
||||
|
||||
self.assertNotEqual(0, test_time.microsecond)
|
||||
self.assertEqual(0, dt_util.strip_microseconds(test_time).microsecond)
|
||||
def test_parse_datetime_returns_none_for_incorrect_format(self):
|
||||
"""Test parse_datetime returns None if incorrect format."""
|
||||
self.assertIsNone(dt_util.parse_datetime("not a datetime string"))
|
||||
|
|
|
@ -39,7 +39,7 @@ class TestUtil(unittest.TestCase):
|
|||
self.assertEqual("True", util.repr_helper(True))
|
||||
self.assertEqual("test=1",
|
||||
util.repr_helper({"test": 1}))
|
||||
self.assertEqual("12:00:00 09-07-1986",
|
||||
self.assertEqual("1986-07-09T12:00:00+00:00",
|
||||
util.repr_helper(datetime(1986, 7, 9, 12, 0, 0)))
|
||||
|
||||
def test_convert(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue