fix date_time validation (#6688)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
RFDarter 2024-05-07 02:47:07 +02:00 committed by GitHub
parent 7b0536fda3
commit 1e196bac98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 47 deletions

View file

@ -169,7 +169,7 @@ async def to_code(config):
{ {
cv.Required(CONF_ID): cv.use_id(DateEntity), cv.Required(CONF_ID): cv.use_id(DateEntity),
cv.Required(CONF_DATE): cv.Any( cv.Required(CONF_DATE): cv.Any(
cv.returning_lambda, cv.date_time(allowed_time=False) cv.returning_lambda, cv.date_time(date=True, time=False)
), ),
} }
), ),
@ -200,7 +200,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args):
{ {
cv.Required(CONF_ID): cv.use_id(TimeEntity), cv.Required(CONF_ID): cv.use_id(TimeEntity),
cv.Required(CONF_TIME): cv.Any( cv.Required(CONF_TIME): cv.Any(
cv.returning_lambda, cv.date_time(allowed_date=False) cv.returning_lambda, cv.date_time(date=False, time=True)
), ),
} }
), ),
@ -230,7 +230,9 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args):
cv.Schema( cv.Schema(
{ {
cv.Required(CONF_ID): cv.use_id(DateTimeEntity), cv.Required(CONF_ID): cv.use_id(DateTimeEntity),
cv.Required(CONF_DATETIME): cv.Any(cv.returning_lambda, cv.date_time()), cv.Required(CONF_DATETIME): cv.Any(
cv.returning_lambda, cv.date_time(date=True, time=True)
),
}, },
), ),
) )

View file

@ -72,21 +72,25 @@ CONFIG_SCHEMA = cv.All(
.extend(_BASE_SCHEMA) .extend(_BASE_SCHEMA)
.extend( .extend(
{ {
cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_time=False), cv.Optional(CONF_INITIAL_VALUE): cv.date_time(
date=True, time=False
),
} }
), ),
"TIME": datetime.time_schema(TemplateTime) "TIME": datetime.time_schema(TemplateTime)
.extend(_BASE_SCHEMA) .extend(_BASE_SCHEMA)
.extend( .extend(
{ {
cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_date=False), cv.Optional(CONF_INITIAL_VALUE): cv.date_time(
date=False, time=True
),
} }
), ),
"DATETIME": datetime.datetime_schema(TemplateDateTime) "DATETIME": datetime.datetime_schema(TemplateDateTime)
.extend(_BASE_SCHEMA) .extend(_BASE_SCHEMA)
.extend( .extend(
{ {
cv.Optional(CONF_INITIAL_VALUE): cv.date_time(), cv.Optional(CONF_INITIAL_VALUE): cv.date_time(date=True, time=True),
} }
), ),
}, },

View file

@ -821,57 +821,50 @@ positive_not_null_time_period = All(
def time_of_day(value): def time_of_day(value):
return date_time(allowed_date=False, allowed_time=True)(value) return date_time(date=False, time=True)(value)
def date_time(allowed_date: bool = True, allowed_time: bool = True): def date_time(date: bool, time: bool):
pattern_str = r"^" # Start of string pattern_str = r"^" # Start of string
if allowed_date: if date:
pattern_str += r"\d{4}-\d{1,2}-\d{1,2}"
if time:
pattern_str += r" "
if time:
pattern_str += ( pattern_str += (
r"(" # 1. Optional Date group r"\d{1,2}:\d{2}" # Hour/Minute
r"\d{4}-\d{1,2}-\d{1,2}" # Date r"(:\d{2})?" # 1. Seconds
r"(?:\s(?=.+))?" # Space after date only if time is following r"(" # 2. Optional AM/PM group
r")?" # End optional Date group r"(\s)?" # 3. Optional Space
)
if allowed_time:
pattern_str += (
r"(" # 2. Optional Time group
r"(\d{1,2}:\d{2})" # 3. Hour/Minute
r"(:\d{2})?" # 4. Seconds
r"(" # 5. Optional AM/PM group
r"(\s)?" # 6. Optional Space
r"(?:AM|PM|am|pm)" # AM/PM string matching r"(?:AM|PM|am|pm)" # AM/PM string matching
r")?" # End optional AM/PM group r")?" # End optional AM/PM group
r")?" # End optional Time group
) )
pattern_str += r"$" # End of string pattern_str += r"$" # End of string
pattern = re.compile(pattern_str) pattern = re.compile(pattern_str)
exc_message = "" exc_message = ""
if allowed_date: if date:
exc_message += "date" exc_message += "date"
if allowed_time: if time:
exc_message += "/"
if allowed_time:
exc_message += "time" exc_message += "time"
schema = Schema({}) schema = Schema({})
if allowed_date: if date:
schema = schema.extend( schema = schema.extend(
{ {
Optional(CONF_YEAR): int_range(min=1970, max=3000), Required(CONF_YEAR): int_range(min=1970, max=3000),
Optional(CONF_MONTH): int_range(min=1, max=12), Required(CONF_MONTH): int_range(min=1, max=12),
Optional(CONF_DAY): int_range(min=1, max=31), Required(CONF_DAY): int_range(min=1, max=31),
} }
) )
if allowed_time: if time:
schema = schema.extend( schema = schema.extend(
{ {
Optional(CONF_HOUR): int_range(min=0, max=23), Required(CONF_HOUR): int_range(min=0, max=23),
Optional(CONF_MINUTE): int_range(min=0, max=59), Required(CONF_MINUTE): int_range(min=0, max=59),
Optional(CONF_SECOND): int_range(min=0, max=59), Required(CONF_SECOND): int_range(min=0, max=59),
} }
) )
@ -885,21 +878,21 @@ def date_time(allowed_date: bool = True, allowed_time: bool = True):
# pylint: disable=raise-missing-from # pylint: disable=raise-missing-from
raise Invalid(f"Invalid {exc_message}: {value}") raise Invalid(f"Invalid {exc_message}: {value}")
if allowed_date: if time:
has_date = match[1] is not None has_seconds = match[1] is not None
if allowed_time: has_ampm = match[2] is not None
has_time = match[2] is not None has_ampm_space = match[3] is not None
has_seconds = match[3] is not None
has_ampm = match[4] is not None
has_ampm_space = match[5] is not None
format = "" format = ""
if allowed_date and has_date: if date:
format += "%Y-%m-%d" format += "%Y-%m-%d"
if allowed_time and has_time: if time:
format += " " format += " "
if allowed_time and has_time: if time:
format += "%H:%M" if has_ampm:
format += "%I:%M"
else:
format += "%H:%M"
if has_seconds: if has_seconds:
format += ":%S" format += ":%S"
if has_ampm_space: if has_ampm_space:
@ -914,12 +907,12 @@ def date_time(allowed_date: bool = True, allowed_time: bool = True):
raise Invalid(f"Invalid {exc_message}: {err}") raise Invalid(f"Invalid {exc_message}: {err}")
return_value = {} return_value = {}
if allowed_date and has_date: if date:
return_value[CONF_YEAR] = date_obj.year return_value[CONF_YEAR] = date_obj.year
return_value[CONF_MONTH] = date_obj.month return_value[CONF_MONTH] = date_obj.month
return_value[CONF_DAY] = date_obj.day return_value[CONF_DAY] = date_obj.day
if allowed_time and has_time: if time:
return_value[CONF_HOUR] = date_obj.hour return_value[CONF_HOUR] = date_obj.hour
return_value[CONF_MINUTE] = date_obj.minute return_value[CONF_MINUTE] = date_obj.minute
return_value[CONF_SECOND] = date_obj.second if has_seconds else 0 return_value[CONF_SECOND] = date_obj.second if has_seconds else 0

View file

@ -172,6 +172,7 @@ datetime:
name: Date name: Date
id: test_date id: test_date
type: date type: date
initial_value: "2000-1-2"
set_action: set_action:
- logger.log: "set_value" - logger.log: "set_value"
on_value: on_value:
@ -185,6 +186,7 @@ datetime:
name: Time name: Time
id: test_time id: test_time
type: time type: time
initial_value: "12:34:56am"
set_action: set_action:
- logger.log: "set_value" - logger.log: "set_value"
on_value: on_value:
@ -198,6 +200,7 @@ datetime:
name: DateTime name: DateTime
id: test_datetime id: test_datetime
type: datetime type: datetime
initial_value: "2000-1-2 12:34:56"
set_action: set_action:
- logger.log: "set_value" - logger.log: "set_value"
on_value: on_value: