datetime entering value when one is not specified - python

I'm currently learning Python and taken it upon myself to learn some data validation. One part I've gotten stuck on is date and time validation. This program takes a number of parameters including date_start, time_start, date_end, and time_end. The catch is I need them in ISO format. Once in that format I need to make sure they are valid. That's where I'm stuck.
from datetime import datetime
def validate_date(date_start, time_start, date_end, time_end):
full_date_start = date_start + time_start
full_date_end = date_end + time_end
try:
formatted_time_start = datetime.strptime(full_date_start, "%Y-%m-%d%H:%M:%S").isoformat(sep="T", timespec="seconds")
formatted_time_end = datetime.strptime(full_date_end, "%Y-%m-%d%H:%M:%S").isoformat(sep="T", timespec="seconds")
return True
except ValueError:
return False
date_start = "2017-06-29"
time_start = "16:24:00"
date_end = "2017-06-"
time_end = "16:50:30"
print(validate_date(date_start, time_start, date_end, time_end))
print("Date Start: " + date_start + "\nTime Start: " + time_start + "\nDate End: " + date_end + "\nTime End: " + time_end)
I was testing some of the code by removing the day for date_end and the output I got back was
2017-06-01T06:50:30
This check should have failed, or I believe it should have since a day was not supplied. Any help would be appreciated and if there is an easier way to do this, I'd take it. Thank you!

If you check the value of full_date_end before the line that should fail is executed, you get this: "2017-06-16:50:30" and since the format you are looking for looks like this "%Y-%m-%d%H:%M:%S" it picks up the first digit of 16 as the day value and the second digit as the hour value.
To avoid this I would suggest using this format: "%Y-%m-%d %H:%M:%S" as the second parameter of the strptime call. But this also requires for you to change the lines where you define full_date_start and full_date_end as:
full_date_start = date_start + ' ' + time_start
full_date_end = date_end + ' ' + time_end
try:
formatted_time_start = datetime.strptime(full_date_start, "%Y-%m-%d %H:%M:%S").isoformat(sep="T", timespec="seconds")
formatted_time_end = datetime.strptime(full_date_end, "%Y-%m-%d %H:%M:%S").isoformat(sep="T", timespec="seconds")
...
I hope that solves your problem.

Related

Trying to filter an api request with <= and >= date tomorrow 0100-2400 if statement

I am new to Python and am having a hard time filtering an api request by datetime: tomorrow basically from hours 0100-2400, only. Time zone is local time. The request prints out as a nested dictionary and I have been able to filter it down to 'validTime' but can't get it filtered anymore from there. My start_time and end_time may be wrong, or my if statement may be wrong, or it's something else. I feel that there is an easy fix for this, I just can't figure it out. Please help. My code is below:
import constants
import requests
import datetime
import json
today = datetime.date.today()
yesterday = today - datetime.timedelta(days=1)
tomorrow = today + datetime.timedelta(days=1)
day_after_tomorrow = today + datetime.timedelta(days=2)
hour1 = datetime.time(1, 0, 0)
hour0 = datetime.time(0, 0, 0)
start_time = ['{}T{}+00:00/PT1H'.format(tomorrow, hour1)]
end_time = ['{}T{}+00:00/PT1H'.format(day_after_tomorrow, hour0)]
response = requests.get(constants.austinfgd, headers=headers)
data = json.loads(response.text)
temperature_data = data['properties']['temperature']['values']
print(temperature_data)
This is what is printed out to this point:
Printed response to temperature_data from website
[{'validTime': '2020-12-11T10:00:00+00:00/PT2H', 'value': 17.77777777777778},
{'validTime': '2020-12-11T12:00:00+00:00/PT1H', 'value': 16.666666666666668},
{'validTime': '2020-12-11T13:00:00+00:00/PT2H', 'value': 17.22222222222222},
...
and so on for a number of days
So, now I need to filter by validTime and I specifically want the hours = to and in between start_time and end_time. So, here is my code for that:
for v in temperature_data:
if ['validTime'] >= start_time and ['validTime'] <= end_time:
At this point, pycharm is telling me to simplifiy the chained comparison and it automatically gives me this:
for v in temperature_data:
if start_time <= ['validTime'] <= end_time:
print(v)
At this point, the only thing that prints out is:
Printed response to v
Process finished with exit code 0
I need to print these values by these times only, so I can dump into a table in postgresql, to be used elsewhere.
What am I doing wrong? I have been googling this for over a week, and I give up. Time to ask for help, please help. Thank you in advance for your help.
So, I changed things up and this seems to have worked. Not sure if there is a better way to code this. And I don't understand why I need to have v['validTime'] in the if statement. Is there a cleaner way to do this?
tomorrow = datetime.datetime.combine(
datetime.date.today() + datetime.timedelta(days=1),
datetime.time(1, 0, 0),
tzinfo=pytz.UTC
)
day_after_tomorrow = datetime.datetime.combine(
datetime.date.today() + datetime.timedelta(days=2),
datetime.time(1, 0, 0),
tzinfo=pytz.UTC
)
start_time = tomorrow.isoformat()
end_time = day_after_tomorrow.isoformat()
response = requests.get(constants.austinfgd, headers=headers)
data = json.loads(response.text)
temperature_data = data['properties']['temperature']['values']
for v in temperature_data:
if start_time <= v['validTime'] <= end_time:
print(v)

ValueError: time data 'None' does not match format '%Y-%m-%dT%H:%M:%S.%f'

For the node 'TransactionDate' i have a logic before updating it for policy"POL000002NGJ".
The logic i am trying to implement is If existing 'TransactionDate' < than today, then add 5 days with current value and parse it to xml.
Transaction Date Format in XML : 2020-03-23T10:56:15.00
Please Note that, If i parsing the DateTime value like below, It works good But i dont want to hardcode the value... I want to Parse it as a string object to handle for any datetime in format ""%Y-%m-%dT%H:%M:%S.%f""...
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = '2020-03-24T10:56:15.00'
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
Below code while parsing it as a DateTime Object, I have an issue.. I got struck here and referenced other answers in stackoverflow and python forums, But still i got struct up here and unable to resolve the issue...
if any help to fix will be a great helpful. Thanks. Below code using lxml and getting help to support below code will helpful. Because i already completed for other nodes. My understanding is Date variable is calling as None.. But struck here to fix.. Please help..
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = str(TransactionDate)
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
Full Code is Below
from lxml import etree
from datetime import datetime, timedelta
import random, string
doc = etree.parse(r'C:\Users\python.xml')
# <PolicyId> - Random generated policy number
Policy_Random_Choice = 'POL' + ''.join(random.choices(string.digits, k=6)) + 'NGJ'
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = str(TransactionDate)
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
#Parsing the Variables
replacements = [Policy_Random_Choice , TransactionDate ]
targets = doc.xpath('//ROW[PolicyId="POL000002NGJ"]')
for target in targets:
target.xpath('./PolicyId')[0].text = replacements[0]
target.xpath('.//TransactionDate')[0].text = replacements[1]
print(etree.tostring(doc).decode())
Sample XML
<TABLE>
<ROW>
<PolicyId>POL000002NGJ</PolicyId>
<BusinessCoverageCode>COV00002D3X1</BusinessCoverageCode>
<TransactionDate>2020-03-23T10:56:15.00</TransactionDate>
</ROW>
<ROW>
<PolicyId>POL111111NGJ</PolicyId>
<BusinessCoverageCode>COV00002D3X4</BusinessCoverageCode>
<TransactionDate>2020-03-23T10:56:15.00</TransactionDate>
</ROW>
</TABLE>
Maybe the find method is wrong. Try this one
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.xpath('//ROW/TransactionDate') # Change find to xpath
Date = str(TransactionDate[0].text) # Use the first one
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")

insert conditional for hours

Good evening, could you help me in how I can put a condition so that a message comes out saying that you can not take an hour because it is already busy ?, I currently have this:
class reserva (models.Model):
_name='gimnasio.reserva'
tipo_reserva=fields.Selection([('clase','Clase'),('evaluacion','Evaluacion')])
fecha_reserva=fields.Date()
start_time=fields.Float()
end_time=fields.Float()
def fecha(self):
if self.star_time==self.star_time:
raise validationError('the hour is busy')
I have another question for you. you know how to configure Datetime only for hour and minutes because I only need hour and minutes but not the date.
To configure Datetime only for hour and minutes.
time = fields.Datetime("time")
custom_time = fields.Char('my_custome_time')
#api.onchange('time')
def _get_time(self):
if self.time:
for rec in self:
# datetime value is a string like 'YYYY-mm-dd HH:MM:SS'
# so just extract string from position 11 to 16
_time = self.time[11:16]
self.custom_time = _time
rec.custom_time = self.custom_time
I think you can use strptime method from datetime module.
from datetime import datetime as dt
start_time = fields.Float()
end_time = fields.Float()
#api.onchange('start_time','end_time')
def _check(self):
records = self.env["gimnasio.reserva"].search([("day", '=', the day you want to check eg. "2019-06-13")])
for rec in records:
ref_start = dt.strptime(str(rec.start_time), "%H:%M")
curr_start = dt.strptime(str(self.start_time), "%H:%M")
if ref_start == curr_start:
raise validationError('the hour is busy')
I didn't debug yet, you can try it.
how to eliminate the default date that you added ("2019-06-13") and that any date should not have the same busy schedule?
In this case you don't need datetime module just
#api.constrains("start_time")
def _check(self):
# search db for any record have same start time.
records = self.env["gimnasio.reserva"].search([('start_time ','=', self.start_time)])
if len(records) > 0:
raise validationError('the hour is busy')

How to modify if-else logic to in a script to retrieve data for T-14 days

I have an exsting script which is used to extract data for T and T-1 day. I tried to modify it extract two weeks data, but the script is not able to search the dates other than current date
Check the code section :
def parse_gov():
reject_patterns = generate_reject_patterns()
today_str = date.today().strftime('%Y.%m.%d')
yesterday = date.today() - timedelta(days=14)
yesterday_str = yesterday.strftime('%Y.%m.%d')
#query_date = date.today()
#query_date = yesterday
query_last = '''select last sym, last source, last lastTimeStamp, last objectName...
query_all = '''select objectName, IONrecType, sym, source, lastTimeStamp, objectName, ....
def query(q, query_date):
if query_date = date.today() - timedelta(days=14):
date_clause = "date <= {date}, ".format(date = query_date)
kdbport = '1000' ( historical database)
else:
date_clause = ""
kdbport = '1001' (current database)
Your else part is not triggering because the comparison is not happening over there.
you need to change
query_date = date.today() - timedelta(days=14):
to
query_date == (date.today() - timedelta(days=14)):
You always use == for comparison, = will assign the value to the variable.

"An integer is required" datetime field

what i wanted to do with this code is get all the datas thats dated older than yesterday. It throws an error "an integer is required" at the line:
date = datetime.date(year, month, yesterday)
So far to my knowledge, its taking year as an integer but not month field. It takes the month field as the default datetime field.
Heres my view:
current = datetime.datetime.now()
yesterday = datetime.datetime.today() + datetime.timedelta(days = -1)
year = datetime.date.today().year
month = datetime.date.today() + relativedelta(months = -1)
date = datetime.date(year, month, yesterday)
hist_obj = Events.objects.filter(uploader = request.user,
start_date__lte = date)
return render_to_response('history.html', {'history_obj':hist_obj})
This code is confusing. yesterday and month are both datetimes, because that's how you defined them in lines 2 and 4. So what are you trying to achieve in the code that throws the error? As the message says, you can't pass a datetime as the day or month parameter to construct another datetime. Especially as, surely, yesterday is already the date that you want? Why can't you simply pass that to the query?
Try this,
day_ago = datetime.date.today() - datetime.timedelta(days=1)
yesterday = datetime.datetime(day_ago.year, day_ago.month, day_ago.day)
hist_obj = Events.objects.filter(uploader = request.user,
start_date__lt = yesterday)
return render_to_response('history.html', {'history_obj':hist_obj})

Categories