How to limit the input in Python for only dates? - python

Im currently working on my project.
I want the user to only be allowed to input a date (ex, January 2). If he enters anything else than a date a message should appear like "This is not a date, try again" repeatedly until a real date is given. How do i do this?
My initial idea was to create a .txt file were i write all the 365 dates and then somehow code that the user is only allowed to enter a string that matches one of the elements in the file, else try again.
I would really apreciate your help

Use dateutil.parser to handle dates of arbitrary formats.
Code
import dateutil.parser
def valid_date(date_string):
try:
date = dateutil.parser.parse(date_string)
return True
except ValueError:
return False
Test
for date in ['Somestring', 'Feb 20, 2021', 'Feb 20', 'Feb 30, 2021', 'January 25, 2011', '1/15/2020']:
print(f'Valid date {date}: {valid_date(date)}')
Output
Valid date Somestring: False # detects non-date strings
Valid date Feb 20, 2021: True
Valid date Feb 20: True
Valid date Feb 30, 2021: False # Recognizes Feb 30 as invalid
Valid date January 25, 2011: True
Valid date 1/15/2020: True # Handles different formats

There is no need to store all possible valid dates in a file.
Use datetime.strptime() to parse a string (entered by the user) into a datetime object according to a specific format.
strptime will raise an exception the input specified does not adhere to the pattern, so you can catch that exception and tell the user to try again.
Wrap it all in a while loop to make it work forever, until the user gets it right.
You can start with this:
from datetime import datetime
pattern = '%B %d, %Y' # e.g. January 2, 2021
inp = ''
date = None
while date is None:
inp = input('Please enter a date: ')
try:
date = datetime.strptime(inp, pattern)
break
except ValueError:
print(f'"{inp}" is not a valid date.')
continue
For a full list of the %-codes that strptime supports, check out the Python docs.

Provide you with several ways to verify the date, these are just simple implementations, and there is no strict check, you can choose one of the methods and then supplement the detailed check by yourself.
Use date(year,month,day)
def isValidDate(year, month, day):
try:
date(year, month, day)
except:
return False
else:
return True
Use date.fromisoformat()
def isValidDate(datestr):
try:
date.fromisoformat(datestr)
except:
return False
else:
return True
Use strptime
def check_date(i):
valids = ['%Y-%m-%d', '%Y%M']
for valid in valids
try:
return strptime(i, valid)
except ValueError as e:
pass
return False
Use regex
def check_date(str):
reg = /^(\d{4})-(\d{2})-(\d{2})$/;
return reg.test(str)

Related

How can I adjust 'the time' in python with module Re

this is a funny question.
I try to find out the right time in some phrases.
I use try-except module and re module
but there is something wrong in my code that can't deal with some tough phrase
As is depicted belong, I input the rediculous time 1997-25-52 or 1996-42-120
it still can output an answer.
def regular_time(time):
"""
部分电影日期带有国家, 例如:'1994-09-10(加拿大)'
正则提取日期
"""
import re
pattern = '^(([1-2]\d{3})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]))'
try:
matches = re.match(pattern, time, flags=0).group()
return matches
except Exception as e:
try:
pattern = '^(([1-2]\d{3})-(0[1-9]|1[0-2]))'
matches = re.match(pattern, time, flags=0).group()+'-01'
return matches
except:
try:
pattern = '^(([1-2]\d{3}))'
matches = re.match(pattern, time, flags=0).group() + '-01-01'
return matches
except:
print('errors')
time='1996-12-58'
regular_time(time)
How can I deal with this problem? Many thanks if you could do me a favor
Question: Default date from invalid datestring
Using datetime handles also leap years!
datetime.datetime.strptime
datetime.date.strftime
For example:
import re
from datetime import datetime
def regular_time(time):
_t = time.split('-')
# allways 3 itmes
while len(_t) < 3:
_t.append('01')
# year month and day ranges
ymd = [(range(1900, 2099), '1900'),
(range(1, 13), '01'),
(range(1, 32), '01')
]
# validate ranges
for n in range(3):
if not int(_t[n]) in ymd[n][0]:
_t[n] = ymd[n][1]
_time = '-'.join(_t)
try:
date = datetime.strptime(_time, '%Y-%m-%d')
print('VALID:{} => {}'
.format(time, date.strftime('%Y-%m-%d')))
except ValueError as e:
if "day is out of range for month" in e:
print('{} for {}, change to 01'.format(e, time))
_t[2] = '01'
regular_time('-'.join(_t))
else:
print('INVALID[{}]:{}'.format(_time, e))
for time in ['1996', '1996-18', '2019-09-31', '2019-01-31',
'1996-12-58', '1997-25-52', '1996-42-120']:
regular_time(time)
Output:
VALID:1996 => 1996-01-01
VALID:1996-18 => 1996-01-01
day is out of range for month for 2019-09-31, change to 01
VALID:2019-09-01 => 2019-09-01
VALID:2019-01-31 => 2019-01-31
VALID:1996-12-58 => 1996-12-01
VALID:1997-25-52 => 1997-01-01
VALID:1996-42-120 => 1996-01-01
Tested with Python 3.6
Your test case returns "1996-12-01", which is that it hits second-level "try-except", since it matches pattern of correct year and month (first failed cause day is unrealistic), then it just simplifies it to the first day of the month by adding "-01".
If you want to keep all parts of the date realistic - don't overwrite original "pattern". But fail it in first step.

Need a password to be equal to the date (d/m/y)

our teacher gave us this assignment to make a "password" (not a login, basically make a variable that is always equal to the date and then "if- else" it so the variable is equal to the date )
the code u see is all I tried, I couldn't find anything on the web.
import datetime
x = datetime.datetime.now()
xd=x.strftime("%d")
xm=x.strftime("%m")
xy=x.strftime("%Y")
Date = [xd,xm,xy]
password=input("what is the password?")
if password==Date:
print("well done")
else:
print("try again")
I have no syntax errors
You're going at it in too "divided" of an approach. You can translate the date into a string all at once:
import datetime
x = datetime.datetime.now()
date = x.strftime("%d%m%Y") # will produce '05212019'
# alternatively: "%d,%m,%Y" would produce '05,21,2019' - you can customize this format
password = input("Enter the password. ")
if password == date:
print("Well done")
else:
print("Try again")
First Date is a reserved word so I recommend using date.
date is a list and password is a string so you need to change Date to string
date = ''.join(date) # 21052019
OR
change password to list (assuming input like 21 05 2019)
password = input("what is the password?").split(' ') # ['21', '05', '2019']
OR
don't create a list and just generate the password/date with datetime
date = x.strftime("%d%m%Y") # 21052016
Not sure which format you're after but you could do something like this and then modify the format so that it looks exactly as you need it:
>>> import datetime
>>> datetime.date.today().strftime("%B %d, %Y")
'May 21, 2019'
You could change to ...
*.strftime("%B%d%Y")
... for example if you needed it to remove spaces and commas.
This site https://www.programiz.com/python-programming/datetime/strftime has a very good format code list (%h, %d, %y, etc...) in case you're needing your time bits in different formats.
Right now, Date is a list and password is a string. You'll need to change one to match the other, or they'll never compare equal.
import datetime
x = datetime.datetime.now()
xd=x.strftime("%d")
xm=x.strftime("%m")
xy=x.strftime("%Y")
Date = xd+","+xm+","+xy
password=input("what is the password?")
if password==Date:
print("well done")
else:
print("try again")

MM/DD/YYYY Date to variable conversion m,d, and y

I am struggling to find the best way to convert the date input given by the user as mm/dd/yyyy to 3 variables. I am unable to split this because I receive an error since it is a 'float'.
>>> date=3/2/2016
>>> date.split('/')
Traceback (most recent call last):
File "<pyshell#152>", line 1, in <module> date.split('/')
AttributeError: 'float' object has no attribute 'split'
what do I need to add to this to make sure it doesn't evaluate the date with division?
def main():
date=input("Enter date mm/dd/yyyy: ")
I want the input date given as mm/dd/yyyy, and then a way to convert this to 3 variables as m=month d=day y=year
What's the best way to do this?
Try str.split:
>>> test_date = "05/12/2016"
>>> month, day, year = test_date.split('/')
>>> print(f"Month = {month}, Day = {day}, Year = {year}")
Month = 05, Day = 12, Year = 2016
I wrote this following piece of code and it works perfectly fine.
>>> date='3/2/2016'
>>> new=date.split('/')
>>> new
['3', '2', '2016']
>>>
>>> m,d,year=new
>>> m
'3'
>>> d
'2'
>>> year
'2016'
>>>
Like Jessica Smith has already pointed it out, date=3/2/2016 evaluates expressions and divides the numbers. It has to be of string string type to be split.
The error "'float' object has no attribute 'split'" suggests that type(date) == float in your example that implies that you are trying to run Python 3 code using Python 2 interpreter where input() evaluates its input as a Python expression instead of returning it as a string.
To get the date as a string on Python 2, use raw_input() instead of input():
date_string = raw_input("Enter date mm/dd/yyyy: ")
To make it work on both Python 2 and 3, add at the top of your script:
try: # make input() and raw_input() to be synonyms
input = raw_input
except NameError: # Python 3
raw_input = input
If you need the old Python 2 input() behavior; you could call eval() explicitly.
To validate the input date, you could use datetime.strptime() and catch ValueError:
from datetime import datetime
try:
d = datetime.strptime(date_string, '%m/%d/%Y')
except ValueError:
print('wrong date string: {!r}'.format(date_string))
.strptime() guarantees that the input date is valid otherwise ValueError is raised. On success, d.year, d.month, d.day work as expected.
Putting it all together (not tested):
#!/usr/bin/env python
from datetime import datetime
try: # make input() and raw_input() to be synonyms
input = raw_input
except NameError: # Python 3
raw_input = input
while True: # until a valid date is given
date_string = raw_input("Enter date mm/dd/yyyy: ")
try:
d = datetime.strptime(date_string, '%m/%d/%Y')
except ValueError: # invalid date
print('wrong date string: {!r}'.format(date_string))
else: # valid date
break
# use the datetime object here
print("Year: {date.year}, Month: {date.month}, Day: {date.day}".format(date=d))
See Asking the user for input until they give a valid response.
You could use .split('/') instead of .strptime() if you must:
month, day, year = map(int, date_string.split('/'))
It doesn't validate whether the values form a valid date in the Gregorian calendar.
Try:
def main():
month, day, year = [int(x) for x in raw_input("Enter date mm/dd/yyyy: ").split('/')]
print "Month: {}\n".format(month), "Day: {}\n".format(day), "Year: {}".format(year)
main()
Output:
Enter date mm/dd/yyyy: 03/09/1987
Month: 3
Day: 9
Year: 1987

How to make strings within strings optional in python

I am writing to write something where there are two variables that are formatted in datetime format. The way the user may input their date and time may have the letter "Z" at the end of it. For example:
"2008-01-01T00:00:01Z"
The user may or may not enter in the "Z" at the end so I want to do something that makes either format acceptable. Here's what I have:
import datetime
b = datetime.datetime.strptime("2008-01-01T00:00:01Z", "%Y-%m-%dT%H:%M:%S")
c = datetime.datetime.strptime("2008-05-01T23:59:00Z", "%Y-%m-%dT%H:%M:%S")
def startTime(b):
try:
datetime.datetime.strptime(b, "%Y-%m-%dT%H:%M:%S")
except:
print "Error: start time is invalid."
def endTime(c):
try:
datetime.datetime.strptime(c, "%Y-%m-%dT%H:%M:%S")
except:
print "Error: end time is invalid."
How about just manually removing the Z if it is there?
user_in = raw_input("Please enter a date")
if user_in.endswith('Z'): user_in = user_in[:-1]
rstrip can remove the Z for you if it exists, and leave the string alone otherwise:
>>> "2008-05-01T23:59:00Z".rstrip("Z")
'2008-05-01T23:59:00'
>>> "2008-05-01T23:59:00".rstrip("Z")
'2008-05-01T23:59:00'
So if you have a date s in string format,
date = datetime.datetime.strptime(s.rstrip("Z"), "%Y-%m-%dT%H:%M:%S")
will handle both cases.

Handling international dates in python

I have a date that is either in German for e.g,
2. Okt. 2009
and also perhaps as
2. Oct. 2009
How do I convert this into an ISO datetime (or Python datetime)?
Solved by using this snippet:
for l in locale.locale_alias:
worked = False
try:
locale.setlocale(locale.LC_TIME, l)
worked = True
except:
worked = False
if worked: print l
And then plugging in the appropriate for the parameter l in setlocale.
Can parse using
import datetime
print datetime.datetime.strptime("09. Okt. 2009", "%d. %b. %Y")
http://docs.python.org/library/locale.html
The datetime module is already locale-aware.
It's something like the following
# German locale
loc = locale.setlocale(locale.LC_TIME, ("de","de"))
try:
date = datetime.date.strptime(input, "%d. %b. %Y")
except:
# English locale
loc = locale.setlocale(locale.LC_TIME, ("en","us"))
date = datetime.date.strptime(input, "%d. %b. %Y")
Very minor point about your code snippet: I'm no Python expert but I'd consider the whole "flag to check for success + silently swallowing all exceptions" to be bad style.
try/expect/else does what you want in a cleaner way, I think:
for l in locale.locale_alias:
try:
locale.setlocale(locale.LC_TIME, l)
except locale.Error: # the doc says setlocale should throw this on failure
pass
else:
print l

Categories