how to substract two dates in django? - python

i am trying to subtracts 'end time' of a ride from its 'start time'. starttime is fetched directly from database(models.py) and line 'start = n[0].driverStarttime' indicates that. Now i use current datetime as 'endtime' of a ride. Variable 'diff' is used to subtract end and start time. but it gives
'TypeError at /driver_panel/endtrip
can't subtract offset-naive and offset-aware datetimes' error. here driver_panel is my application in project. Driverbooking table is used to fetch start time. DateTimeField is used for store start and endtime. here is the code...
def endtrip(request):
if request.method == 'GET':
dbid = request.GET.get('driverBookID')
if dbid:
n = Driverbooking.objects.all().filter(driverBookID=dbid)
name = n[0].customerID
start = n[0].driverStartTime
end = datetime.datetime.now()
diff = end - start
total = diff * 10
a = Driverbooking.objects.get(driverBookID=dbid)
a.driverStatus = "end"
a.driverEndTime = end
a.driverAmount = total
a.save()
did = request.session['uid']
x = Driverside.objects.all().filter(driverID=did)
rate = x[0].driverFPH
d = Driverside.objects.get(driverID=did)
d.driverIsAvailable = "yes"
d.save()
context = {"name":name,"start":start,"end":end,"rate":rate,"t":total}
return render(request, "driverbill.html", context)
return redirect('driverhome')

The problem raises because you seem to be subtracting "start time" (which probably has timezone info) and "end time" (which has no timezone).
Simple solution is to use the correct current time with timezone, like the timezone docs suggest.
Instead of this line:
end = datetime.datetime.now()
try this:
from django.utils import timezone as tz
end = tz.now()

Related

How do I specify a start date using time at a particular time of the day with yfinance

Please am trying to get the stock date at a specify time of the date adding the time of which i want the stock data to be gotten from as well to so far i did something like this but i keep getting error saying data - F: Data doesn't exist for startDate = 1666286770, endDate = 1666287074
this is my code below
def watchlist():
timezone = pytz.timezone('US/Eastern')
print(type(timezone))
aware = dt.datetime.now(timezone).time()
print(aware)
global pastTime
pastTime = dt.datetime.now(timezone) - dt.timedelta(minutes=5) # time of 5minutes ago
print(pastTime)
for x in ticks:
toStr = str(x)
syb = yf.Ticker(toStr)
data = pd.DataFrame(syb.history(interval="1m",period='1d',))
data2 = pd.DataFrame(syb.history(interval="1m",period='1d',start=pastTime))
if data['Open'].sum() < data2['Open'].sum():
print(data['Open'].sum())
print(data2['Open'].sum())
print('Watch stock')
else:
print(toStr, 'Proceed to sell with robinhood')
watchlist()
Screen shot of issue

Filter icalendar events based on a time frame breaks because of datetime comparison

I am trying to pull events from an ics file within the next month but making my own datetime and comparing to the datetime in the ics file doesn't seem to be working and is giving the error TypeError: can't compare offset-naive and offset-aware datetimes
I tried the answers found here but still get the same error. Below is the code I am using.
def read_from_cal():
g = open('calendar.ics', 'rb')
gcal = Calendar.from_ical(g.read())
year = datetime.now().year
month = datetime.now().month
day = datetime.now().day
hour = datetime.now().strftime("%H")
minute = datetime.now().strftime("%M")
next_month = datetime(int(year), int(month)+1, int(day), int(hour), int(minute), 0, tzinfo=pytz.UTC)
#next_month = next_month.replace(tzinfo=pytz.UTC)
for component in gcal.walk():
if component.name == "VEVENT":
# time printed out in format:
# year-month-day hour:min:sec
summ = component.get('summary')
start = component.get('dtstart').dt
end = component.get('dtend').dt
if now <= start <= next_month:
print("Worked")
print(summ, start, end)
I've tried both with using replace to change my time to utc and just putting it in the next_month variable itself and they both give the same error above.
I've also tried this and this to no avail.
I have tried with a .ics file generated here, so could not be the same problem, but in some cases start is a datetime.datetime and in other cases is a datetime.date.
This solution worked with my .ics file
from icalendar import Calendar
from datetime import datetime
from dateutil.relativedelta import relativedelta
def read_from_cal():
g = open('example.ics', 'rb')
gcal = Calendar.from_ical(g.read())
today = datetime.now()
next_month = today + relativedelta(months=1)
for component in gcal.walk():
if component.name == "VEVENT":
summ = component.get('summary')
start = component.get('dtstart').dt
end = component.get('dtend').dt
if isinstance(start, datetime):
start = start.replace(tzinfo=None)
if start <= next_month:
print("Worked (datetime)")
print(summ, start, end)
else:
# some events are stored as a date
if start <= next_month.date():
print("Worked (date)")
print(summ, start, end)
read_from_cal()

Retrieving Dates more than Current Time in From Django Database

I am struggling to understand how the date queries work in Django as I am storing a database with train times. I want to get times that are greater than the current time.
The query looks like this, but returns zero results:
latestdepartures = LatestDepartures.objects.filter(station=startstation,earliest__gte=timezone.now().astimezone(pytz.utc))
My database has the entry below for example.
When I run the query, I get the results below (first line is print(timezone.now().astimezone(pytz.utc)):
2020-08-01 15:49:06.610055+00:00
<QuerySet []>
The code which adds the data to the database looks like:
def convert_date_time(o):
if isinstance(o, datetime):
return o.__str__()
def updateservices(stationname,destination):
now = datetime.now()
# dd/mm/YY H:M:S
datenow = now.strftime("%d/%m/%Y")
board = DARWIN_SESH.get_station_board(stationname)
stationdict = dict()
stationdict['from'] = stationname
stationdict['name'] = board.location_name
stationdict['servicelist']=[]
services = board.train_services
for s in services:
traindict = dict()
service_details = DARWIN_SESH.get_service_details(s.service_id)
traindict['departuretime'] = datetime.strptime(datenow + " " + service_details.std,'%m/%d/%Y %H:%M').astimezone(pytz.utc)
traindict['callingpoints'] = []
callingpoints = service_details.subsequent_calling_points
for c in callingpoints:
if c.crs == destination:
callingpointdict = dict()
callingpointdict['code'] = c.crs
callingpointdict['name'] = c.location_name
callingpointdict['arrivaltime'] = datetime.strptime(datenow + " " + c.st,'%m/%d/%Y %H:%M').astimezone(pytz.utc)
traindict['callingpoints'].append(callingpointdict)
if len(traindict['callingpoints']) > 0:
stationdict['servicelist'].append(traindict)
#For getting the minimum departure
departures = [s['departuretime'] for s in stationdict['servicelist']]
#Store the train departure object in the database
stationdata = json.dumps(stationdict, default=convert_date_time)
LatestDepartures.objects.create(
station = stationname,
earliest = min(departures),
services = stationdata
)
return stationdata
servicedetails.std will be a time represented in 24hours in string format, for example "17:00".
Can anyone help, I am not sure if I am meant to change the date format somewhere or if it is to do with the way the datetime object is created by adding the time.
UPDATE:
Now storing the date in a different format as '%d/%m/%Y %H:%M':
Now I get dates that are greater than, but once the time current time has exceeded the earliest in the database, the query still returns results. Example output is:
2020-08-01 17:31:21.909052+00:00
print(timezone.now().astimezone(pytz.utc))
2020-08-01 18:03:00+00:00 - Time in database

parse dates with icalendar and compare to python datetime

I have an .ics file from which I would like to extract all of the events that occur on today's day. I think I'm having trouble converting the icalendar DTSTART and DTEND to python datetimes. I've tried to follow the documentation at icalendar.readthedocs.org. The list I'm getting is empty, which should not be the case.
This is my code:
import urllib2
import json
from datetime import datetime
from icalendar import Calendar, Event, vDatetime
def getTodayEvents(icsFile):
cal = Calendar.from_ical(icsFile)
today = datetime.now().date()
entries = []
for event in cal.walk('VEVENT'):
dtstart = event['DTSTART']
dtend = event['DTEND']
start = vDatetime.from_ical(dtstart) //Trouble here?
end = vDatetime.from_ical(dtend)
if start <= today <= end:
entry = {'summary' : event['SUMMARY'] }
entries.append(entry)
output = json.dumps(entries)
return output //This list is empty
And this is what the and ics entry looks like:
BEGIN:VEVENT
SUMMARY:Jonny Smith
DTSTART;VALUE=DATE:20140731
DTEND;VALUE=DATE:20150802
UID: 12345
CLASS:PUBLIC
PRIORITY:5
DTSTAMP:20141006T160145Z
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
LOCATION:Mansfield\, GA
X-MICROSOFT-CDO-APPT-SEQUENCE:0
X-MICROSOFT-CDO-BUSYSTATUS:FREE
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-CDO-INSTTYPE:0
X-MICROSOFT-DISALLOW-COUNTER:FALSE
END:VEVENT
DTSTART, DTEND properties have .dt attribute:
#!/usr/bin/env python
import json
from datetime import date
import icalendar # $ pip install icalendar
today = date.today()
calendar = icalendar.Calendar.from_ical(ics_file)
entries = [dict(summary=event['SUMMARY'])
for event in calendar.walk('VEVENT')
if event['DTSTART'].dt <= today <= event['DTEND'].dt]
print(json.dumps(entries, indent=2, sort_keys=True))
Output
[
{
"summary": "Jonny Smith"
}
]
The event object has a method .decoded(), which gives you either a datetime.date object (as in your case, the .ics only has a date) or a datetime.datetime object. For the datetime.datetime object, you additionally need to convert the correct timezone.
In order to make a unified comparison, I convert everything to a string and then compare the string. This ended up, that I wrote an isEventToday method:
from datetime import datetime, timezone, timedelta
def isEventToday(event):
if event.get('dtstart') == None:
dtstart = ""
else:
temp = event.decoded('dtstart')
if isinstance(temp, datetime):
dtstart = temp.astimezone().strftime("%Y-%m-%d")
else:
dtstart = temp.strftime("%Y-%m-%d")
if event.get('dtend') == None:
dtend = ""
else:
temp = event.decoded('dtend')
if isinstance(temp, datetime):
dtend = temp.astimezone().strftime("%Y-%m-%d")
else:
# dtend for day events is the day AFTER the event, so we
# need to substract one!
dtend = (temp - timedelta(days=1)).strftime("%Y-%m-%d")
today = datetime.today().date().strftime("%Y-%m-%d")
if dtstart != "" and dtstart == today:
return True
if dtend != "" and dtend == today:
return True
if dtstart != "" and dtend != "" and dtstart <= today and today <= dtend:
return True
return False
The code does not look nice to me, but it is working.
Check to see if you've got a discrepancy between data types or content in your if start <= today <= end: comparison. Take a look (in debugger or so) at what are the types and content of those three variables. I think you'll find that the comparison is comparing things that are legal to compare, but not compatible enough to give you the answer you expect (i.e., do the start and end times of this event overlap todays date?)
Your today is a datetime structure, which can be compared to other datetimes as you intend. Perhaps your vDatetime.from_ical(dtstart) is returning something other than a datetime. A quick glance at the source looks like it should be returning a datetime though. Maybe you've got a time zone issue? Look at the content of all three and check which is < or == or > others.
If that's the case, add a time zone to your calls to vDatetime.from_ical() calls;
start = vDatetime.from_ical(dtstart,'Europe/Amsterdam') #or wherever you are
Your time in the .ics indicates Z -- i.e., GMT.
If you need to do more with dates, see working with time.

Google Calendar API event always minusing one day

I am creating dict obj and sending it up to google calendar as with googles own example on their API documentation. I read a mssql database and then produce a csv file of the results. I then use the cdv information to write the events.
Snippets from my code.
def count_leaveduration(sdate, fdate):
try:
date_format = "%Y.%m.%d"
cmp_sdate = datetime.strptime(sdate, date_format)
cmp_fdate = datetime.strptime(fdate, date_format)
delta = cmp_fdate - cmp_sdate
return delta.days, cmp_sdate, cmp_fdate
except Exception as e:
input_logging('error', 'Cannot Count Leave Duration - Exception: %s' % e)
duration, sdate, fdate = count_leaveduration(line['FIRSTDAYOFABSENCE'], line['LASTDAYOFABSENCE'])
event['summary'] = '%s - Leave' % line['NAME1']
event['location'] = 'Out Of Office'
# date type here instead because all day event for duration.
event['start'] = {'date': '%s' % sdate.strftime('%Y-%m-%d')}
event['end'] = {'date': '%s' % fdate.strftime('%Y-%m-%d')}
event['attendees'] = [{'email': line['ELECTRONICMAILADDRESS']}]
appbuildobj.events().insert(calendarId=robj, body=event).execute()
The entries work fine in general but if the duration is longer than one day it seems to chop a day off on the calendar entry even though the date should be the finish date which is being presented to the calendar event dict. Of course the work around is to do something like this:-
fdate = fdate + timedelta(days=1)
However, Id like to know if anyone knows the reason for this happening?
It's hidden but I've found it:-
https://developers.google.com/google-apps/calendar/concepts
Such an event starts on startDate and ends the day before endDay. For example, a one-day event should have its start date set to day and its end date set to day + 1.
So I have fixed this with:-
fdate = fdate + timedelta(days=1)

Categories

Resources