I'll ignore the incorrect use of is not
for now, lets focus on the core issue: your while
test is almost always false. Sure, it is false for your target condition:
>>> (1 is not 1) and (4 is not 4)
False
Think about it:
1 is not 1
is False, because 1 is equal to 1, so it's the opposite of your test.
4 is not 4
is False, because 4 is equal to 4, so it's also the opposite of your test.
But, if you changed one of those values in the test you would still get False
:
1 is not 1
is False,
17 is not 4
is True,
but your while
loop only runs if both tests are true, because you used and
. Since today is a Tuesday, but the date is the 17th of the month, the while
loop will not run. On other days, it'll run until the first tuesday after the current date, or when it reaches the 4th of a month, whatever comes first.
You want to run the loop is one or the other is true, instead, so you want to use or
here, but see below for a better option.
Note that the correct test for integer inequality, is !=
, so you wanted to use:
while this_d.weekday() != 1 or this_d.day != 4:
but it might be easier to say:
while not (this_d.weekday() == 1 and this_d.day == 4):
You probably started with this_d.weekday() == 1 and this_d.day == 4
and tried to invert that test, but you can't just add not
to those tests and have it pass. You fell in to the classic boolean inversion trap and want to learn about De Morgan's laws:
not (A or B) = (not A) and (not B)
not (A and B) = (not A) or (not B)
The inverse of A and B
is (not A) or (not B)
. But, sometimes it is just clearer to keep the not (A and B)
test as is.
Further notes:
- You don't need the first
if
test. The loop will not run when the condition is met too, so the whole if
branch is redundant.
- You can use
this_d += datetime.timedelta(days=1)
instead of this_d = this_d + datetime.timedelta(days=1)
. Look up augmented assignment, it is easier and shorter here.
- I'd return the
date
object. That would make your function re-usable in more situations. Sometimes you don't need to format a date object immediately!
So, I'd write it as:
def tue_the_fourth():
this_d = datetime.date.today()
while not (this_d.weekday() == 1 and this_d.day == 4):
this_d += datetime.timedelta(days=1)
return this_d
and only format the date when you have to convert it to a string, as late as possible.