How to: python time notation to strip (leading) zero

HI,

using

time = '%02d:%02d:%02d' % (dt.hour, dt.minute, dt.second)

the time is always displayed with 2 digits for hr, min and seconds. I like however to strip the leading zero for the hour, and leave seconds out completely if at the full minute exactly.

using:

time = '%2d:%02d:%d' % (dt.hour, dt.minute, dt.second)

does the correct thing for the hour (at least i think so, have to see what happens at 00:01:01…), but still shows me only 0 for the seconds when it is under the first 10 seconds of the minute.

Can I somehow do this, without introducing complete new if then else logic?

Cant find the docs on this in the https://docs.python.org library or https://pyformat.info so its a bit of a guess right now…

or using the ‘new’ notation:

time = '{:d}:{:d}:{:2d}'.format(dt.hour, dt.minute, dt.second)

You can use this to get rid of the leading zero for the hour

time.lstrip("0").replace(" 0", " ")

I don’t know if there is an easier solution then if then else to get rid of the seconds if they are 0.

Do I understand correctly?

Time given: 02:05:00
Time desired: 2:05

Time given: 02:05:09
Time desired: 2:05:9

Why do you need such a special format for your time string?

no for seconds I need the leading zero.

It is merely a question of saving space in a card, and optical hygiene. Can leave the seconds out if they’re :00, need both digits always for the minutes, even at :00, and can leave out the leading 0 for the hour:

its to display this:

08

last automation ran at 10:10:00 so could have been dislplayed as 10:10.
It’s no big deal, but since anything is possible in HA/Python, I was looking for a way :wink:

This works for me.

if dt.second == 0:
  mytime = f"{dt.hour}:{str(dt.minute).zfill(2)}"
else:
  mytime = f"{dt.hour}:{str(dt.minute).zfill(2)}:{str(dt.second).zfill(2)}"

ok thanks, that isnt a very complex if then else after all :wink:
I do get this error though:

Error loading script last_automation.py: Line 22: JoinedStr statements are not allowed.

got it to work with:

if dt.second == 0:
    time = '{:02d}:{:02d}'.format(dt.hour, dt.minute)
else:
    time = '{:02d}:{:02d}:{:02d}'.format(dt.hour, dt.minute, dt.second)

16

does {dt.hour} show a leading zero?

No, dt.hour is an integer, so it doesn’t show a leading zero. Same goes for dt.minute and dt.second.

The error you get is due to the f-string literal notation to represent a string, looks like this isn’t supported in home assistant scripts, I tested it in AppDaemon and there it worked :slight_smile:

Try this:

if dt.second == 0:
time = ‘{:d}:{:02d}’.format(dt.hour, dt.minute)
else:
time = ‘{:d}:{:02d}:{:02d}’.format(dt.hour, dt.minute, dt.second)

Basically if you want a leading 0 -> {:02d}
if you don’t want a leading 0 -> {:d}

thanks for explaining.

it is indeed due to the representation order I can use the fact it doesnt show the leading zero for the hour, but want to have that for the seconds.

still, what will happen at midnight?

do suppose it would need to be 00:01:01 and not 0:01:01 …
although that doesn’t look too bad tbh

At midnight it will show 0:00. At 00:01:01 it will show 0:00:01.

You can easily test this with an Online Python IDE.

Add the following code:

from datetime import time

dt = time(0, 0, 1)

if dt.second == 0:
    mytime = '{:d}:{:02d}'.format(dt.hour, dt.minute)
else:
    mytime = '{:d}:{:02d}:{:02d}'.format(dt.hour, dt.minute, dt.second)

print(mytime)

and change the time to check what it will show at this time.

Python also allows formatting strings using strftime. It doesn’t have logic to shave off seconds when zero, but it has a built-in way of handling hours.

from datetime import time

dt = time(0, 0, 1)
mytime = f'{dt:%-H:%M:%S}' if dt.second else f'{dt:%-H:%M}'
print(mytime)
1 Like

Yes totally forgot about strftime :slight_smile:
However with your code, I’m not sure if it will work due to the f-string literal notation, which didn’t work for him in my example above.

1 Like

Good point. In that case:

from datetime import time

dt = time(0, 0, 1)
mytime = '{:%-H:%M:%S}'.format(dt) if dt.second else '{:%-H:%M}'.format(dt)
print(mytime)

if I remember correctly from my earlier efforts in other scripts, these imports aren’t allowed either…

Fri Oct 11 2019 11:54:42 GMT+0200 (CEST)

Error executing script: __import__ not found
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 195, in execute
    exec(compiled.code, restricted_globals, local)
  File "last_automation.py", line 1, in <module>
ImportError: __import__ not found

These lines in the examples are only for testing:

from datetime import time

dt = time(0, 0, 1)

They are simply used to create the dt object without having your full script. You can safely skip them in your code :slight_smile:

Didnt even do that yet, I only had the import line added. Its the sandboxed Python environment in Hassio I fear…

If you just replace your original line:

time = '%02d:%02d:%02d' % (dt.hour, dt.minute, dt.second)

with:

time = '{:%-H:%M:%S}'.format(dt) if dt.second else '{:%-H:%M}'.format(dt)

Does that not work?

yes it does, and i must confess it was what I started to look for in the beginning (the dash ‘%-h’) but didn’t realize it could be done directly in python scripts… I use it in yaml all the time :blush: duh.

no it doesnt… sorry:

Fri Oct 11 2019 13:16:44 GMT+0200 (CEST)

Error executing script: '__import__'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 195, in execute
    exec(compiled.code, restricted_globals, local)
  File "last_automation.py", line 21, in <module>
KeyError: '__import__'

thought it to show correctly at startup, but now that I dont see anything happening, checked the log and above appears…

Hm, not sure what that’s about to be honest. Would you mind posting your script?

sure, Ill post it with all comments so you can see what Ive tried.

# from datetime import time
# https://community.home-assistant.io/t/how-to-python-time-notation-to-strip-leading-zero/141787/13

# Get params
event = data.get('event')
#logger.error("LAST AUTOMATION: " + str(event))
# Sample: <Event call_service[L]: domain=automation, service=trigger, service_data=entity_id=automation.call_service_event_automation, service_call_id=1972124944-486>

# Find the automation name
#** pos_start = event.find('entity_id=')+10
pos_start = event.find('entity_id=')+21
pos_end = event.find(',', pos_start)

# Get the entity_id
#** entity_id = event[pos_start:pos_end]
entity_id = 'automation.' + event[pos_start:pos_end]

# get the state object
state = hass.states.get(entity_id)

# Make a time string in 24 hour format
#time_string = datetime.datetime.now().strftime('%I:%M')
dt = datetime.datetime.now() #state.attributes.get('last_triggered') #

if dt.second == 0:
    time = '{:02d}:{:02d}'.format(dt.hour, dt.minute)
else:
    time = '{:d}:{:02d}:{:02d}'.format(dt.hour, dt.minute, dt.second)

# time = '{:%-H:%M:%S}'.format(dt) if dt.second else '{:%-H:%M}'.format(dt)
#time = '%2d:%02d:%02d' % (dt.hour, dt.minute, dt.second)
# try to get the automation friendly name
msg = []

try:
    msg = state.name
except:
    msg = None

if msg:
   if not msg.startswith('Set '):
       # Sensor update
       hass.states.set('sensor.last_automation', '{}: {}'.format(msg,time), {
#            'unit_of_measurement': 'Aut',
            'friendly_name': 'Last autom',
            'entity_picture': '/local/buttons/play-mode-repeat.png' })

Sorry for the late reply. So the code above is the one creating this error?

Error executing script: '__import__'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 195, in execute
    exec(compiled.code, restricted_globals, local)
  File "last_automation.py", line 21, in <module>
KeyError: '__import__'

The only immediate thing I can think of is that you are calling datetime.datetime.now() without first calling import datetime.

Unless this isn’t the full code and you import datetime somewhere else?

The error is referencing a problem with line 21. What is on that line of your script?