How to "set_state" for input_datetime component? getting "TypeError: Object of type 'datetime' is not JSON serializable"

I’m getting the following TypeError when trying to set the datetime of an input_datetime component from appdaemon. Anyone able to assist?

Error:

“TypeError: Object of type ‘datetime’ is not JSON serializable”

Trying to call:

self.set_state(“input_datetime.both_date_and_time”, state = new_time)

Code Except:

# Get Time
current_time_str = self.get_state("input_datetime.both_date_and_time", attribute="state")
print("Current Time String: %s" % current_time_str)
current_time = datetime.datetime.strptime(current_time_str, "%Y-%m-%d %H:%M:%S")
print("Current Time: %s" % current_time)
# Determine New time
new_time = current_time + datetime.timedelta(minutes = 10)
print("New Time: %s" % new_time)
# Set New Time
self.set_state("input_datetime.both_date_and_time", state = new_time)

Error:

Current Time String: 2018-03-01 10:00:00
Current Time: 2018-03-01 10:00:00
New Time: 2018-03-01 10:10:00
2018-03-27 15:28:31.977776 WARNING AppDaemon: Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 543, in worker
    funcref(args["event"], data, args["kwargs"])
  File "./apps/energyOptimisation.py", line 45, in increase_time_event_listener
    self.set_state("input_datetime.both_date_and_time", state = new_time)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/appdaemon/plugins/hass/hassapi.py", line 134, in set_state
    apiurl, headers=headers, json=new_state, verify=certpath
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/sessions.py", line 494, in request
    prep = self.prepare_request(req)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/sessions.py", line 437, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/models.py", line 308, in prepare
    self.prepare_body(data, files, json)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/requests/models.py", line 458, in prepare_body
    body = complexjson.dumps(json)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'datetime' is not JSON serializable

Section of configuration.yaml

script:
  test_appdaemon_event:
    sequence:
      # This is Home Assistant Script Syntax
      - event: appdaemon_event
        event_data:
          name: optimise
          message: event to trigger optimise manually

  test_appdaemon_event_increase_time:
    sequence:
      # This is Home Assistant Script Syntax
      - event: appdaemon_event_increase_time
        event_data:
          name: increase_time
          message: event to trigger optimise manually

this seemed to work:

self.set_state("input_datetime.both_date_and_time", attributes = {
    "year": 2018,
    "month": 3,
    "day": 1,
    "hour": 10,
    "minute": 30,
    "second": 0,
    }
)

hang on - this seems to only the “text label” on input_datetime and not the real datetime for the control… :frowning:

Still need to solve the ““TypeError: Object of type ‘datetime’ is not JSON serializable”” issue, so the “state” can be passed…ideas???

I think that the state value would have to be a string. But exactly what format that string would take I don’t know, as I haven’t used an input_datetime.

@gpbenton - I might try that next/tomorrow…

If you want to actually change the underlying widget you must use a service call. set_state() will literally just change the state but it won;t do anything like for instance turning a light on or off, you need the appropriate service call for that.

Is there way to confirm what Json data/syntax is actually required for a call?

I’m trying the “call service” out in the GUI and have tried a few things. For example:

input_datetime.set_datetime
{
“state”: “2018-03-01 10:00:00”
}

But here I get an “extra keys not allowed”. So how to tell?

2018-03-28 06:54:45 ERROR (MainThread) [homeassistant.core] Invalid service data for input_datetime.set_datetime: extra keys not allowed @ data['state']. Got '2018-03-01 10:00:00'

In the doco for input_datetime it does highlight:

|Service|Data|Description|
|---|---|---|
|set_datetime|time|This can be used to dynamically set the time.|
|set_datetime|date|This can be used to dynamically set the date.|

How this raises the question how to represent a “date” in JSON? And the problem re my initial post “Object of type ‘datetime’ is not JSON serializable”” Any ideas?

i think you started out good, but probably need to give back a string.
the format should be the same as what you get with get_state so:

current_time_str = self.get_state("input_datetime.both_date_and_time", attribute="state")
print("Current Time String: %s" % current_time_str)
current_time = datetime.datetime.strptime(current_time_str, "%Y-%m-%d %H:%M:%S")
print("Current Time: %s" % current_time)
# Determine New time
new_time = current_time + datetime.timedelta(minutes = 10)
print("New Time: %s" % new_time)
new_time_string = new_time.strftime("%Y-%m-%d %H:%M:%S")
# Set New Time
self.set_state("input_datetime.both_date_and_time", state = new_time_string)

will probably work.

@ReneTode - thanks 90% works now, however the text showing the time doesn’t get updated on the UI?

So it does seem to correctly update the datetime in the component, as when I repeat the call it reads back the updated value, which is good. It’s just that on the UI the datetime doesn’t get updated.

Wonder if this is where the “call_service” is required as opposed to set_state?

2018-03-28 09:10:11.048551 INFO energyOptimisation: ---------------- increase_time_event_listener starting -----------------
Current Time String:2018-03-01 10:20:00:
Current Time: 2018-03-01 10:20:00
New Time: 2018-03-01 10:30:00
New Time String:2018-03-01 10:30:00:
2018-03-28 09:10:16.216971 INFO energyOptimisation: ---------------- increase_time_event_listener starting -----------------
Current Time String:2018-03-01 10:30:00:
Current Time: 2018-03-01 10:30:00
New Time: 2018-03-01 10:40:00
New Time String:2018-03-01 10:40:00:

could very well be.
the input_select and input_number also have their own service calls.

but i dont have an input_date so i cant check that for you.

I think I have it. Amongst other things I the service name in the UI has a “.” in between, whereas in this code I needed to use a “/”. That is: “input_datetime/set_datetime”

date_str = new_time.strftime("%Y-%m-%d")
time_str = new_time.strftime("%H:%M:%S")
self.call_service("input_datetime/set_datetime", 
  entity_id = "input_datetime.both_date_and_time",
  date = date_str,
  time = time_str
)
5 Likes

i know some services are not like you expect.
i never know what to use, and use mostly trial on error. :wink:

reviving this thread as I am having also trouble.
CoDe:

            elif current_inputtype == "input_datetime":
                if "/" in current_value and ":" in current_value:
                    self.mylog("date and time" )
                    self.call_service("input_datetime/set_datetime", 
                        self.mylog("datetime {}".format(current_value) )
                        entity_id = current_helper,
                        date = current_value.split(" "[0]).strftime("%Y-%m-%d"),
                        time = current_value.split(" "[1]).strftime("%H:%M:%S"))
                elif "/" in current_value:
                    self.mylog("date {}".format(current_value) )
                    self.call_service("input_datetime/set_datetime", 
                        entity_id = current_helper,
                        date = current_value)
                elif ":" in current_value:
                    self.mylog("time {}".format(current_value) )
                    self.call_service("input_datetime/set_datetime", 
                        entity_id = current_helper.strftime("%Y-%m-%d"),
                        time = current_value.strftime("%H:%M:%S"))

Log:

2022-08-24 11:54:48.643138 WARNING HASS: Code: 400, error: 400: Bad Request
2022-08-24 11:54:48.642952 WARNING HASS: Error calling Home Assistant service default/input_datetime/set_datetime
2022-08-24 11:54:48.638825 INFO aur: date 12/12/21
2022-08-24 11:54:48.633950 WARNING HASS: Code: 400, error: 400: Bad Request
2022-08-24 11:54:48.633774 WARNING HASS: Error calling Home Assistant service default/input_datetime/set_datetime
2022-08-24 11:54:48.631689 INFO aur: Current Helper Type input_datetime.
2022-08-24 11:54:48.631216 INFO aur: Updating Attribute aura_datetime3 with value 12/12/21.
2022-08-24 11:54:48.630737 INFO aur: Current Helper input_datetime.a_datetime3.
2022-08-24 11:54:48.630224 INFO aur: _____________________________
2022-08-24 11:54:48.628631 INFO aur: time 00:00:00
2022-08-24 11:54:48.623802 WARNING HASS: Code: 400, error: 400: Bad Request
2022-08-24 11:54:48.623607 WARNING HASS: Error calling Home Assistant service default/input_datetime/set_datetime
2022-08-24 11:54:48.622073 INFO aur: Current Helper Type input_datetime.
2022-08-24 11:54:48.621587 INFO aur: Updating Attribute aura_datetime2 with value 00:00:00.
2022-08-24 11:54:48.621107 INFO aur: Current Helper input_datetime.a_datetime2.

So what I am trying to do is updating some input_datetime via service calls.
I receive a 400 BAD request and no update is done.
I have now tried all possible combo
@ReneTode @proggie any clue?

self.call_service("input_datetime/set_datetime", 
                        self.mylog("datetime {}".format(current_value) )
                        entity_id = current_helper,
                        date = current_value.split(" "[0]).strftime("%Y-%m-%d"),
                        time = current_value.split(" "[1]).strftime("%H:%M:%S"))

this will probably make that the app doesnt reinitialise, so your output is from and old version from the app.

self.call_service("input_datetime/set_datetime", 
                        entity_id = current_helper.strftime("%Y-%m-%d"),
                        time = current_value.strftime("%H:%M:%S"))

and this will also give errors.

I tried also without the string formatting:

date = current_value.split(" "[0])

same result

This is kind of a weird way to deal with datetime stuff but why don’t you try current_value.split(" ")[0]

whoa what a typo. yes () should be like that

look closely to the 2 codeblocks i copied.
in the first you got

self.mylog("datetime {}".format(current_value) )

INSIDE the call service!! and without a comma behind it that will 100% error out and the app wont restart. so you should look in your error log when you restart an app.

and in the second 1 you got

entity_id = current_helper.strftime("%Y-%m-%d")

and im 100% sure that current_helper is no datetime, and entity shouldnt be a datetime :wink:

Still not getting hold of inputdatetime.

Can You please post 3 working examples of service calls to date time to, respectively set:

  • a date and time
  • a date
  • a time

So basically the 3 types of input_datetime available

I have working all other types of input helpers not the date time
Thank You

           ```

i think the problem you have is that you try to use 1 input_datetime for date, time and datetime.
and as far as i understand the docs that wont work.

an input_datetime is time, date OR datetime.

if you always want it in the same entity, you will need to create a datetime entity, and then you will need to add a fixed date to the time you get and a fixed time to the date you get, so
1900-01-01 20:00:00
2023-05-07 00:00:00
2022-10-12 21:00:00

1 Like