User4497
User4497

Reputation: 75

Overwrite element in list

I'm creating a function that returns the time. I wanted it to display am/pm instead of having a max of 24h. So I needed to first substract 6 on the hour if it is above 12.

But nothing is happening, I'm not even getting an error and I have no idea what is the cause for this. Can someone explain what is the cause?

import datetime

MONTHS = 'jan feb mar apr may jun jul aug sep oct nov dec'.upper().split(' ')
def get_date():
    # 01-OCT-1978 04:31:17
    
    date = datetime.datetime.today().__str__().split(' ')
    date[0] = date[0].split('-')
    
    if int(date[1].split(':')[0]) > 12:
        date[1].split(':')[0] = str(int(date[1].split(':')[0]) - 12)
        
    real_date = date[0][2] + '-' + MONTHS[int(date[0][1])] + '-' + date[0][0] + ' ' + date[1].split('.')[0]
                
    return real_date

print(get_date())
# 07-APR-2021 21:56:12

Upvotes: 2

Views: 138

Answers (3)

CodenameLambda
CodenameLambda

Reputation: 1496

The reason this doesn't work is fundamentally based on the issue that methods like split return a new piece of data, that was generated out of its inputs, but is not linked to it anymore after it is returned; in this line of your code:

date[1].split(':')[0] = str(int(date[1].split(':')[0]) - 12)

To give some easier examples:

s = "a:b:c"
l = s.split(":")  # this returns a *new* list `["a", "b", "c"]`
s += ":d"  # `l` is still `["a", "b", "c"]`, even though `s` is now `"a:b:c:d"`
l[0] = "e"  # `s` is still `"a:b:c:d"`, even though `l` was changed to `["e", "b", "c"]`

You can, however, overwrite the old data with the function that undoes split - join / redo the operation when the original data changes:

s = "a:b:c"
l = s.split(":")  # Note that this is won't actually do anything since it's going to be overwritten two lines down
s += ":d"  # `s` is now `"a:b:c:d"`
l = s.split(":")  # `l` is now `["a", "b", "c", "d"]`
l[0] = "e"  # `s` is still unchanged...
s = ":".join(l)  # but can be updated from the changed `l`, such that it will now be `e:b:c:d`

Note that them not being linked makes more sense when you consider functions that actually lose information when applied - such as len:

s = "abc"
len(s) = 4  # Note that this is not valid syntax; but if it were, what should `s` now be?

As was noted by others, the best solution to this would be to replace this with strftime, as this does the job more easily, more concisely, it's easier to read and it's the "proper" way to do it.

Upvotes: 2

Jacob Lee
Jacob Lee

Reputation: 4680

I would recommend splitting each value into variables. Using lots of list indexes and methods is fine, but it is much more readable by using variables instead of many list indexes.

str_datetime = datetime.datetime.today().__str__().split(' ')
(year, month, day), (h, m, s) = (str_datetime[0].split('-'), str_datetime[1].split(':'))
if int(h) > 12:
    h = str(int(h) - 12)
    ampm = "PM"
else:
    ampm = "AM"
date = f"{day}-{MONTHS[int(month)]}-{year} {h}:{m}:{round(float(s))} {ampm}"

This would give the following value of date:

'07-APR-2021 7:08:59 PM'

However, instead of using such lengthy methods, you can just use the datetime.datetime.strftime() method. For example:

date = datetime.datetime.now().strftime("%d-%b-%Y %I:%M:%S %p")

This gives the following output:

'07-Mar-2021 18:56:37 PM'

For reference, here is a list of datetime.datetime.strftime format codes

Upvotes: 1

W. Ding
W. Ding

Reputation: 689

For your problem, I would suggest a whole new solution that better utilize the powerful datetime module.

import datetime

date = datetime.datetime.today().strftime("%Y-%m-%d %I:%M %p")

print(date)
# '2021-03-08 10:54 AM'

The reason your code doesn't work is that you are editing a temporary variable that is not stored. You have to create a variable to store the split list, and then concatenate them back.

If you change the middle part to

t = date[1].split(':')
if int(t[0]) > 12:
    t[0] = str(int(t[0]) - 12)
date[1] = ':'.join(t)

which will work. But I have to remind you, this way will create further complexity in appending 'AM' and 'PM', while using the module will be much convenient.

Upvotes: 3

Related Questions