3
\$\begingroup\$

I have created a program which works out days, hours, minutes, seconds and milliseconds until a date which the user inputs. Is it possible to shorten/make the output a little clearer?

from datetime import datetime
while True:
 inp = input("Enter date in format yyyy/mm/dd hh:mm:ss")
 try:
 then = datetime.strptime(inp, "%Y/%m/%d %H:%M:%S")
 break
 except ValueError:
 print("Invalid input")
now = datetime.now()
diff = then - now
print(diff, "until", inp)
print(diff.total_seconds(),"seconds")
SuperBiasedMan
13.5k5 gold badges37 silver badges62 bronze badges
asked Dec 16, 2015 at 21:44
\$\endgroup\$
3
  • \$\begingroup\$ Welcome to Code Review. It's actually unclear what you're asking for. What do you think should be improved in your program code? \$\endgroup\$ Commented Dec 16, 2015 at 21:47
  • \$\begingroup\$ Good point, I'll edit \$\endgroup\$ Commented Dec 16, 2015 at 21:48
  • \$\begingroup\$ Probably you should show what your actual output looks like, and what you want to make clearer. Your edit didn't improve very much I'm afraid. My downvote still stays until you make your question clear. \$\endgroup\$ Commented Dec 16, 2015 at 22:30

2 Answers 2

7
\$\begingroup\$

Here you going to get two different answers in one for your question. One on the output issue, and one your coding. Let's start with the coding part.

I do like that keep trying until you get a proper input, however there is no way to exit this loop besides providing a legal date. This shouldn't be a problem as you suggest the valid format, but yet again it could be bad.

Even for small scripts I would get into the habit of using functions, and avoid code at the top level. Not only can that focus your coding, but it could also for you function to be called as part of a module, and allow for testing using modules like doctest. One common idiom to use is the if __name__ == '__main__': which then can call your function.

Using it as function could also allow for looping your script if you want to check multiple days, or allow dates to input from the command line using argument parsing.

Your names are not terrible, but they are not entirely good either. The now also kind of hides the datetime.now(). It's legal, and your code does work, but having variables the same as functions is a little unfortunate.

Regarding simplifying output

I expect that you would want output similar to "2 years, 4 months, 7 days, 8 hours, 40 minutes and 4 seconds". This however is harder than you think, as get the correct amount of months and years is tricky. I.e. How many days and months are there between 2015年02月03日 and 2015年03月04日? Is it "1 month and 1 day" or is it "29 days"? The latter would be correct if the month always have 30 days, and the first is the more conventional answer based on human logic.

The same kind of logic applies to years, where you'll possibly get the output wrong according to human logic. And with leap years the equation gets even worse. Both for months and days difference calculation.

As such you might want to evaluate what you actually want to output, and how to achieve this. One road could be to do it the hard way, and that is compare the dates part by part, but this will expand your code quite a bit.

I.e. when comparing the 2015年11月16日 with 2016年03月14日, you could try with "1 year" but as the to month is lower than from month, you have to subtract one and add 12 months to the difference. For months you'll then get "3 - 11 + 12" making 4 months. But yet again you'll have an issue since the 14th is before the 16th...

And this time you have to take into account the days of the previous month, February of 2016, which has 29 days, making the correct number of days: "14 -ひく 16 +たす 29 = 27", and correct the month number to 3 months.

So the final difference is to be: 3 months and 27 days. (That is if I'm not mistaken, and done something wrong in my calculations.)

answered Dec 16, 2015 at 23:11
\$\endgroup\$
1
  • \$\begingroup\$ Thx for the help, and good point about the output \$\endgroup\$ Commented Dec 17, 2015 at 18:40
1
\$\begingroup\$

Your error message can't be much more specific without parsing the string to try determine the error, but users don't read well, so it's worth reminding them why they're getting an error.

print("Invalid input. Please match the format *exactly*.")
print("Also non existent dates like month 13 are not valid.")

holroy's right that now isn't a great name, but you don't even need it. You could just evaluate the result of now() in place:

diff = then - datetime.now()
print(diff, "until", inp)
print(diff.total_seconds(),"seconds")

There's nothing wrong with this, I personally find it cleaner since it's more obvious you only need that result once and it's easier to see how diff is being calculated.

answered Dec 17, 2015 at 15:43
\$\endgroup\$
1
  • \$\begingroup\$ Thx, always like to have my code as short as possible and that has helped \$\endgroup\$ Commented Dec 17, 2015 at 18:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.