Check Date Format from a Python Tkinter entry widget - python-3.x

Using a Tkinter input box, I ask a user for a date in the format YYYYMMDD.
I would like to check if the date has been entered in the correct format , otherwise raise an error box. The following function checks for an integer but just need some help on the next step i.e the date format.
def retrieve_inputBoxes():
startdate = self.e1.get() # gets the startdate value from input box
enddate = self.e2.get() # gets the enddate value from input box
if startdate.isdigit() and enddate.isdigit():
pass
else:
tkinter.messagebox.showerror('Error Message', 'Integer Please!')
return

The easiest way would probably be to employ regex. However, YYYYMMDD is apparently an uncommon format and the regex I found was complicated. Here's an example of a regex for matching the format YYYY-MM-DD:
import re
text = input('Input a date (YYYY-MM-DD): ')
pattern = r'(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])'
match = re.search(pattern, text)
if match:
print(match.group())
else:
print('Wrong format')
This regex will work for the twentieth and twentyfirst centuries and will not care how many days are in each month, just that the maximum is 31.

Probably you've already solved this, but if anyone is facing the same issue you can also convert the data retrieved from the entry widgets to datetime format using the strptime method, and using a try statement to catch exceptions, like:
from datetime import *
def retrieve_inputBoxes():
try:
startdate = datetime.strptime(self.e1.get(), '%Y-%m-%d')
enddate = datetime.strptime(self.e2.get(), '%Y-%m-%d')
except:
print('Wrong datetime format, must be YYYY-MM-DD')
else:
print('startdate: {}, enddate: {}').format(startdate, enddate)
Note that the output string that will result will be something like YYYY-MM-DD HH:MM:SS.ssssss which you can truncate as follows the get only the date:
startdate = str(startdate)[0:10] #This truncates the string to the first 10 digits
enddate = str(enddate)[0:10]
In my opinion, this method is better than the Regex method since this method also detects if the user tries to input an invalid value like 2019-04-31, or situations in which leap years are involved (i.e. 2019-02-29 = Invalid, 2020-02-29 = Valid).

Related

How to differentiate between a dateutil parsed date and a datetime with 0 for all time values

As far as I can tell there is no way to distinguish the difference between these two date strings ('2020-10-07', '2020-10-07T00:00:00') once they are parsed by dateutil. I really would like to be able to tell the difference between a standalone date and a date with a timestamp of zero.
import dateutil.parser
import datetime
date_str = '2020-10-07'
time_str = '2020-10-07T00:00:00'
s = dateutil.parser.parse(date_str)
e = dateutil.parser.parse(time_str)
The ultimate goal is to set the time to the beginning of the day in the end of the day when it is a standalone date but leave the date alone when there is a time included. Get close with something like this but it still can't differentiate from this one case. If do you know of any good solution to this that would be really helpful.
if s == e and s.time() == datetime.time.min:
e = datetime.datetime.combine(e, datetime.time.max)
Post is somewhat useful but it's outdated and I'm not even sure that it would work for my use case. Finding if a python datetime has no time information
Here's a function which uses a simple try/except to test if the input can be parsed to a date (i.e. has no time information) or a datetime object (i.e. has time information). If the input format is different from ISO format, you could also implement specific strptime directives.
from datetime import date, time, datetime
def hasTime(s):
"""
Parameters
----------
s : string
ISO 8601 formatted date / datetime string.
Returns
-------
tuple, (bool, datetime.datetime).
boolean will be True if input specifies a time, otherwise False.
"""
try:
return False, datetime.combine(date.fromisoformat(t), time.min)
except ValueError:
return True, datetime.fromisoformat(t)
# do nothing else here; will raise an error if input can't be parsed
for t in ('2020-10-07', '2020-10-07T00:00:00', 'not-a-date'):
print(t, hasTime(t))
# output:
# >>> 2020-10-07 (False, datetime.datetime(2020, 10, 7, 0, 0))
# >>> 2020-10-07T00:00:00 (True, datetime.datetime(2020, 10, 7, 0, 0))
# >>> ValueError: Invalid isoformat string: 'not-a-date'

Trying to Pass date to pandas search from input prompt

I am trying to figure out how to pass a date inputted at a prompt by the user to pandas to search by date. I have both the search and the input prompt working separately but not together. I will show you what I mean. And maybe someone can tell me how to properly pass the date to pandas for the search.
This is how I successfully use pandas to extract rows in an excel sheet if any cell in column emr_first_access_date is greater than or equal to '2019-09-08'
I do this successfully with the following code:
import pandas as pd
HISorigFile = "C:\\folder\\inputfile1.xlsx"
#opens excel worksheet
df = pd.read_excel(HISorigFile, sheet_name='Non Live', skiprows=8)
#locates the columns I want to write to file including date column emr_first_access_date if greater than or equal to '2019-09-08'
data = df.loc[df['emr_first_access_date'] >= '2019-09-08', ['site_name','subs_num','emr_id', 'emr_first_access_date']]
#sorts the data
datasort = data.sort_values("emr_first_access_date",ascending=False)
#this creates the file (data already sorted) in panda with date and time.
datasort.to_excel(r'C:\\folder\sitesTestedInLastWeek.xlsx', index=False, header=True)
However, the date above is hardcoded of course. So, I need the user running this script to input the date. I created a very basic working input prompt with the following:
import datetime
#prompts for input date
TestedDateBegin = input('Enter beginning date to search for sites tested in YYYY-MM-DD format')
year, month, day = map(int, TestedDateBegin.split('-'))
date1 = datetime.date(year, month, day)
Obviously I want to pass TestedDateBegin to pandas, changing the pertinent code line:
data = df.loc[df['emr_first_access_date'] >= '2019-09-08', ['site_name','subs_num','emr_id', 'emr_first_access_date']]
to something like:
data = df.loc[df[b]['emr_first_access_date'] >= 'TestedDateBegin', ['site_name','subs_num','emr_id', 'emr_first_access_date']]
Obviously this doesn't work. But how do I proceed? I am very new to programming so I not always clear how to proceed. Does the date inputted in TestedDateBegin need to be added to a return? Or should it be put in a single item list? What is the right approach? Thx!
This is resolved.
I had to remove the single quotes around TestedDateBegin as python, of course, interpreted that as a string and not a variable. Living and learning. :-)
data = df.loc[df[b]['emr_first_access_date'] >= TestedDateBegin,['site_name','subs_num','emr_id', 'emr_first_access_date']]

Using if condition in datetime format

I was given a question to get two time input from user as a function(opening_time,closing_time) and I had to determine the difference between the time,but if one of these values are not in time format,the returned value should be -1.I have computed the time difference but,I am unable to fix a condition that if any one of the variable is not in time format,return -1.
Please I am new to coding,so apologize for any mistake and be kind to write simple solution,not so complex one.
from datetime import datetime
def compute_opening_duration(opening_time, closing_time):
str_format = "%H:%M:%S"
if opening_time or closing_time != datetime.time.str_format:
print(-1)
else:
tdelta = datetime.strptime(closing_time,str_format)
- datetime.strptime(opening_time,str_format)
print(tdelta)
Try this - it will try to cast the inputs to a datetime using your provided string format. If it fails on either one, it will print -1.
from datetime import datetime
def compute_opening_duration(opening_time, closing_time):
str_format = "%H:%M:%S"
try:
t_open_time = datetime.strptime(closing_time,str_format)
t_closing_time = datetime.strptime(opening_time,str_format)
tdelta = datetime.strptime(closing_time,str_format) - datetime.strptime(opening_time,str_format)
print(tdelta)
except:
print(-1)
compute_opening_duration("04:10:21", "08:22:12")

Python string to datetime-date

I've got lots of dates that look like this: 16.8.18 (American: 8/16/18) of type string. Now, I need to check if a date is in the past or future but, datetime doesn't support the German format.
How can I accomplish this?
from datetime import datetime
s = "16.8.18"
d = datetime.strptime(s, "%d.%m.%y")
if d > datetime.now():
print('Date is in the future.')
else:
print('Date is in the past.')
Prints (today is 20.7.2018):
Date is in the future.
The format used in strptime() is explained in the manual pages.

How to add a day onto a date parsed string?

I am trying to do a simple add a day to my substring text that i've parsed into a date but it is not displaying correctly.
Below is the code:
def dateTimeDate = Date.parse("yyyy-mm-dd", textfromjson.substring(0,10)).format("yyyy-mm-dd")
def futureDateTimeDate = dateTimeDate + 1
When I do two logs for both defs, the original date and the future date which I want to be next day, I receive this output:
logs:
log.warn dateTimeDate
log.error futureDateTimeDate
output:
2018-02-23
2018-02-231
How can I get this to work so that it outputs: 2018-02-24 and not 2018-02-231
The answers posted already correctly point out that the date value needs to be incremented before it's formatted back into a String.
To this, I would like to add that if you're on Java 8 you can use its new Date/Time API as an alternative to java.util.Date, which can be problematic (even apart from mixing up 'm' and 'M' in format strings).
import java.time.*
def future = LocalDate.parse(textfromjson.substring(0,10)) + Period.ofDays(1)
You're parsing a String into a Date and then formatting it back into a String. Add to the Date object, not the String object.
def dateTimeDate = Date.parse("yyyy-mm-dd", textfromjson.substring(0,10))
def futureDateTimeDate = dateTimeDate + 1
log.warn dateTimeDate.format("yyyy-MM-dd")
log.error futureDateTimeDate.format("yyyy-MM-dd")
Also note that you probably want to be using MM (month in year) not mm (minute in hour).

Resources