Why is it "%m/%d/%y %H:%M" and not "%-m/%-d/%y %-H:%M"

Screen Link:

My Code:

# The `potus` list of lists is available from
# the earlier screen where we created it

# Examples: '12/18/15 16:30', '1/6/15 9:30'

date_format = "%-m/%-d/%y %-H:%M"

for row in potus:
    appt_start_date = row[2]
    row[2] = dt.datetime.strptime(appt_start_date, date_format)

What I expected to happen:
I expected this to pass.

What actually happened:

---> 10     row[2] = dt.datetime.strptime(appt_start_date, date_format)
...
ValueError: '-' is a bad directive in format '%-m/%-d/%y %-H:%M'

Referring to https://strftime.org/ and based on these examples of date and time format: ‘12/18/15 16:30’, ‘1/6/15 9:30’:

Which I translate to:
“month NOT zero-padded”/“Day NOT zero-padded”/“Year without century zero-padded” “Hour (24-hour clock) NOT zero-padded”:“Minute as either”

Using the equivalent code this is:
“%-m/%-d/%y %-H:%M”
Yet this causes an error. And the answer required is “%m/%d/%y %H:%M”.

Why?

1 Like

Hello @idris.mohamed.islam, Welcome to the Community.
Have a look at the date format
image
the date separator is / and that for the time is :, date and time are separated by a space. Therefore the date_format should be "%m/%d/%y %H:%M"

As @info.victoromondi mentioned, it is not zero padded (i.e. not 01/06/15 09:30 etc). Zero padding means adding additional 0s in the date/time strings.

You yourself have mentioned it here.

Thus there is no need to use the %-m etc to specify the format of the data and time.

1 Like

It seems like you guys are saying the same thing as me, but coming to a different conclusion.

The logic I’m following is that I should explain how date_string is formatted through the date_format variable given that:
datetime_object = dt.datetime.strptime(date_string, date_format)

Please tell me if this logic is incorrect.

https://strftime.org/ says:
%m Month as a zero-padded decimal number. 09
and…
%-m Month as a decimal number. (Platform specific) 9

So why should I use ‘%m’ when the month in this example date ‘1/6/15 9:30’ is obviously not zero-padded?

2 Likes

@idris.mohamed.islam:

Please refer to this article.

The Python datetime module documentation explicitly specifies the format strings it supports, and this extension is not given. Thus, while this is supported in GNU date and GNU strftime() , it isn’t available in Python datetime .

1 Like

Thanks for the guidance.

Hi Idris! I was wondering how you managed to bypass this problem… I’m pretty much in the exact same situation, the format of my dates is also ‘1/6/15 9:30’ .

Using the %m/%d/%y %H:%M line of code doesn’t work because it doesn’t fit my data, so it returns the following error:
" ValueError: time data ‘8’ does not match format '%m/%d/%Y %H:%M' "

And using "%-m/%-d/%y %-H:%M" returns the error you mentioned:
" ValueError: ‘-’ is a bad directive in format '%-m/%-d/%Y %-H:%M' "

So did you manage to find a solution?

Thanks!!

For part10 of this mission

Workable solution

There may be bugs if you copy DQ solution. Here’s my solution.

app_lengths = dict()

for row in potus:

    start_date = row[2]
    end_date = dt.datetime.strptime(row[3], "%m/%d/%y %H:%M")
    length = end_date - start_date 
    appt_lengths[length] = appt_lengths.get(length, 0) + 1

min_length = min(appt_lengths)
max_length = max(appt_lengths)

Note that

  • row[3] is of string type with format as "%m/%d/%y %H:%M"

  • row[2] is of datetime.datetime type.

  • Suppose appt_lengths is empty. Then min(appt_lengths) and max(appt_lengths) will throw an error because an empty sequence.

Additional question to answer

Change to storing name instead of counting the frequency.

max or min will use the length on the value of the dictionary.

Use defaultdict because we don’t need to check if a key exists or not, simply add into the dictionary.

from collections import defaultdict 
appt_lengths = defaultdict(list)

for row in potus:
    start = row[2]
    end = dt.datetime.strptime(row[3], "%m/%d/%y %H:%M")
    length = end - start 
    appt_lengths[length].append(row[0])
    
min_length = min(appt_lengths)
max_length = max(appt_lengths)

most_visitor_in_key = max(appt_lengths, key = lambda x: len(appt_lengths[x]))
print("Most visitors in the dictionary key:")
print(appt_lengths[most_visitor_in_key])

longest_time_delta_in_key = max(appt_lengths) # or max(appt_lengths.keys())
print("Longest time delta in the dictionary key:")
print(appt_lengths[longest_time_delta_in_key])

Notes:

  • max_length = max(appt_lengths) is the maximum key of the dictionary = longest time delta (time differences between start and end.)

  • min_length = min(appt_lengths) is the minimum key of the dictionary = shortest time delta (time differences between start and end.)

  • max(appt_lengths) and max(appt_lengths.keys())is the same.

  • min(appt_lengths) and min(appt_lengths.keys()) is the same.

Hi vera. I guess I think I understand the issue I had. I hope this will shed light on yours. pretty much I used https://strftime.org/ guide for the wrong method.

So the exercise required converting a string to a datetime object. For this we use datetime.datetime.strptime().

The reference I used is (https://strftime.org/) is for the opposite; converting a datetime object to a string. For this you can use the code in strftime.org to specify how you want your string to look. And the guide works fine for that. Try the example code below.
‘’’
from datetime import datetime as dt

now = dt.now()
print(now)
print(now.strftime(’%m’)) # Zero padding.
print(now.strftime(’%-m’)) # Non-zero padding.
‘’’
For strptime I don’t think you need to know whether a string is zero-padded or not. Python can probably figure it out if the string isn’t convoluted. But I’m a noob so maybe don’t pay too much attention to me. Hope this helped though.