class Course:
def __init__(self, name, classroom, instructor, day, start_time, end_time):
self.name = name
self.classroom = classroom
self.instructor = instructor
self.day = day
self.start_time = start_time
self.end_time = end_time
class Schedule:
def __init__(self):
self.courses = []
program = [["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"]]
def add_course(self, course):
self.courses.append(course)
def print_schedule(self):
days = ["Monday","Tuesday","Wednesday","Thursday","Friday"]
program = [["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"],["9","10","11","12","13","14","15","16","17"]]
for course in self.courses:
for j in range(course.start_time-9,course.end_time-8):
program[days.index(course.day)][j] += f" {course.name} class from {course.instructor} at {course.classroom}"
for i in range(len(days)):
print(days[i],":")
for k in program[i]:
print(k)
schedule = Schedule()
schedule.add_course(Course("Physics","MED A11","James","Monday",9,11))
schedule.add_course(Course("Logic Design","EEB 4105","Jack","Wednesday",9,10))
schedule.add_course(Course("Logic Design","EEB 4205","Jack","Wednesday",15,17))
schedule.print_schedule()
Here I wanted to create an weekly schedule, I want it to write something when two classes collide. So their self.day need to be same and the times need to intersect.
For times I can do something like
time = {for i in range(start_time,end_time+1)}
if time1.intersection(time2) != 0:
#...
But I don't know how to reach 2 different Course elements at the same time. Also would be great if you have any suggestions for this code.
You can add a method to the Course class that checks it against another Course to see if they collide. When you add a course, have it loop through the existing courses to see if it collides with the existing courses in your Schedule.
class Course:
def __init__(self, name, classroom, instructor, day, start_time, end_time):
self.name = name
self.classroom = classroom
self.instructor = instructor
self.day = day
self.start_time = start_time
self.end_time = end_time
def check_collision(self, other):
if self.day == other.day:
if other.start_time < self.start_time < other.end_time:
return True
if other.start_time < self.end_time < other.end_time:
return True
if self.start_time < other.start_time < self.end_time:
return True
if self.start_time < other.end_time < self.end_time:
return True
return False
class Schedule:
def __init__(self):
self.courses = []
self.program = [
["9","10","11","12","13","14","15","16","17"],
["9","10","11","12","13","14","15","16","17"],
["9","10","11","12","13","14","15","16","17"],
["9","10","11","12","13","14","15","16","17"],
["9","10","11","12","13","14","15","16","17"],
]
def add_course(self, course):
for c in self.courses:
if course.check_collision(c):
print(f'New course has collision with course: {c.name} on {c.day}: {c.start_time}-{c.end_time}')
break
else:
self.courses.append(course)
def print_schedule(self):
days = ["Monday","Tuesday","Wednesday","Thursday","Friday"]
program = [x.copy() for x in self.program]
for course in self.courses:
for j in range(course.start_time-9,course.end_time-8):
program[days.index(course.day)][j] += f" {course.name} class from {course.instructor} at {course.classroom}"
for i in range(len(days)):
print(days[i],":")
for k in program[i]:
print(k)
So based on your Code, what you can do is define a compare function for the class Schedule, you make a Schedule object to hold many courses. So if you want to access a course within a Schedule you need to do schedule.courses[i]. But I suggest you add the following function to the courses class to solve your problem.
def compare_course(self, other_course):
my_time = {i for i in range(start_time, end_time+1)}
other_time = {i for i in range(other_course.start_time, other_course.end_time+1)}
if my_time.intersection(other_course.time) != set():
return "Course Collides"
else:
return "Course does not collide"
I used a tutorial I found online to create an event calendar in Python. I've tried to improve it to schedule events that may have a start and end time range that overlap months. Meaning it may start in June and end in July. I've got it partially figured out...I can display the events based on the start day being lte day in the Python HTMLCalendar module. I can't figure out how to pick up the remaining day for July 1. June displays perfectly. Thanks in advance for any thoughts.
Here's my code...
HTMLCALENDAR Utility..
class Calendar(HTMLCalendar):
def __init__(self, year=None, month=None, dropdown=None):
self.dropdown = dropdown
self.year = year
self.month = month
super(Calendar, self).__init__()
# formats a day as a td
# filter events by day
def formatday(self, day, requests):
requests_per_day = requests.filter(start_time__day__lte=day,start_time__month=self.month)
d = ''
for request in requests_per_day:
d += f'<li> {request.get_html_url} </li>'
if day != 0:
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
return '<td></td>'
# formats a week as a tr
def formatweek(self, theweek, requests):
week = ''
for d, weekday in theweek:
week += self.formatday(d, requests)
return f'<tr> {week} </tr>'
# formats a month as a table
# filter events by year and month
def formatmonth(self, withyear=True):
# requests = VacationRequest.objects.filter(Q(vacation_calendar=self.dropdown,start_time__year=self.year,start_time__month=self.month) | Q(vacation_calendar=self.dropdown,start_time__year=self.year,end_time__month=self.month)).distinct()
requests = VacationRequest.objects.filter(vacation_calendar=self.dropdown,start_time__year=self.year,start_time__month=self.month)
cal = f'<table border="0" cellpadding="0" cellspacing="0" class="calendar">\n'
cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
cal += f'{self.formatweekheader()}\n'
for week in self.monthdays2calendar(self.year, self.month):
cal += f'{self.formatweek(week, requests)}\n'
cal += f'</table>\n'
cal += f'<h1 class="title107">Vacation Schedule For {self.formatmonthname(self.year, self.month, withyear=withyear)}</h1>\n'
return cal
My View...
class VacationRequestCalendarView(LoginRequiredMixin,generic.ListView):
model = VacationRequest
template_name = 'vacation_request_calendar_view.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
dropdown = (self.request.GET.get("dropdown", None))
d = get_date(self.request.GET.get('month', None))
cal = Calendar(d.year, d.month, dropdown)
cal.setfirstweekday(calendar.SUNDAY)
html_cal = cal.formatmonth(withyear=True)
vacation_calendar = VacationCalendar.objects.get(id=self.request.GET.get("dropdown", None))
context['calendar'] = mark_safe(html_cal)
context['dropdown'] = dropdown
context['next_month'] = next_month(d)
context['prev_month'] = prev_month(d)
context['vacation_calendar'] = vacation_calendar
return context
def get_object(self, queryset=None):
return get_object_or_404(VacationCalendar, id=self.request.GET.get("dropdown"))
def get(self, request, *args, **kwargs):
dropdown=self.request.GET.get("dropdown")
if dropdown is not None:
if VacationCalendar.objects.filter(id=dropdown,team_members=self.request.user):
self.object_list = self.get_queryset()
context = self.get_context_data(object=self.object_list)
return self.render_to_response(context)
else:
raise Http404
else:
messages.add_message(self.request, messages.INFO, 'Vacation Calendar is required.')
return HttpResponseRedirect(reverse('VacationRequests:vacation_request_by_calendar_name'))
def get_date(req_month):
if req_month:
year, month = (int(x) for x in req_month.split('-'))
return date(year, month, day=1)
return datetime.today()
def prev_month(d):
first = d.replace(day=1)
prev_month = first - timedelta(days=1)
month = 'month=' + str(prev_month.year) + '-' + str(prev_month.month)
return month
def next_month(d):
days_in_month = calendar.monthrange(d.year, d.month)[1]
last = d.replace(day=days_in_month)
next_month = last + timedelta(days=1)
month = 'month=' + str(next_month.year) + '-' + str(next_month.month)
return month
This displays my event for the month of June as I would hope...
But it does not show up on July 1...
My event has an end time in July...and a start time in June....
How can I get this event to show up on July 1 as well?
My latest attempt at this is close.....
events = VacationRequest.objects.filter(Q(vacation_calendar=dropdown,start_time__year = d.year,start_time__month = d.month)
| Q(vacation_calendar=dropdown,end_time__month = d.month )).distinct().order_by('start_time')
Still trying to work it out...
requests = VacationRequest.objects.filter(Q(vacation_calendar=self.dropdown,start_time__year=self.year,start_time__month=self.month)
| Q(vacation_calendar=self.dropdown,start_time__year=self.year,end_time__month=self.month)).distinct()
Seemed to do the trick.
I have a question about accessing the object class from the list in python, I have compared my cases to the questions that were on stack overflow but that didn't work. I present the problem as follows
Class Booking has the properties start_date, end_date
from datetime import *
class Booking:
def __init__(self):
self.year = int(input("Enter the Year: "))
self.month = int(input("Enter the Month: "))
self.day = int(input("Enter the Day: "))
self.start_date = datetime.now()
self.end_date = datetime(self.year, self.month, self.day)
Class Room is abstract class
I create a booking(list) to store the object of the Booking class which is initialized when the Room class is initialized.
from abc import *
from booking import Booking
class Room(ABC):
bookings = []
def __init__(self, price, capacity):
self.booking = Booking()
self.price = price
self.capacity = capacity
self.bookings.append(self.booking)
#abstractmethod
def is_booked(self, start_date, end_date):
pass
SingleBed inherits Room(ABC) with price = 150 and capachity =2
from room import Room
class Singlebed(Room):
def __init__(self):
super(Singlebed, self).__init__(150, 2)
def is_booked(self, start_date, end_date):
if start_date >= end_date:
print("EndDate must be greater than StartDate")
is_Booked = False
for check_booking in self.bookings:
is_Booked = check_booking... (I wants to access objects.end_date in class Booking is saved in bookings)
single1 = Singlebed()
single2 = Singlebed()
single3 = Singlebed()
single4 = Singlebed()
single5 = Singlebed()
My question: How do I access object.end_date which is initialized with single1, single2, ...
You are iterating over your self.bookings so "check_booking" is your Booking instance and contains the attribute start_date, end_date, year, month, day
def is_booked(self, start_date, end_date):
if start_date >= end_date:
print("EndDate must be greater than StartDate")
is_Booked = False
for check_booking in self.bookings:
is_Booked = check_booking.start_date
I am trying to trigger a method in my models to run by hitting a url.When it hits it returns and error saying "unsupported operand type(s) for -: 'datetime.datetime' and 'NoneType'".
views.py
from django.shortcuts import render
from rest_framework import viewsets
from .serializers import EntrySerializer
from .models import Entry
class EntryView(viewsets.ModelViewSet):
serializer_class = EntrySerializer
queryset = Entry.objects.all()
entryId = Entry.objects.filter(end_time__isnull=True).values('id')
# returns <QuerySet [{'id': 8}]>
for id in entryId:
entryIdNum = id['id']
#returns 8
entry = Entry()
def ToggleView(request):
entry.toggle_paused()
entry.save()
models.py
from django.db import models
from django.db.models import F, ExpressionWrapper, fields
from django.utils import timezone
from dateutil.relativedelta import relativedelta
from decimal import Decimal
class Entry(models.Model):
start_time = models.DateTimeField()
end_time = models.DateTimeField(blank=True, null=True, db_index=True)
seconds_paused = models.PositiveIntegerField(default=0)
pause_time = models.DateTimeField(blank=True, null=True)
comments = models.TextField(blank=True)
date_updated = models.DateTimeField(auto_now=True)
hours = models.DecimalField(max_digits=11, decimal_places=5, default=0)
def _str_(self):
return self.TUID
#property
def total_hours(self):
"""
Determined the total number of hours worked in this entry
"""
total = self.get_total_seconds() / 3600.0
# in case seconds paused are greater than the elapsed time
if total < 0:
total = 0
return total
#property
def is_paused(self):
"""
Determine whether or not this entry is paused
"""
return bool(self.pause_time)
def pause(self):
"""
If this entry is not paused, pause it.
"""
print('Pause Hit')
if not self.is_paused:
self.pause_time = timezone.now()
def pause_all(self):
"""
Pause all open entries
"""
entries = self.user.timepiece_entries.filter(end_time__isnull=True)
for entry in entries:
entry.pause()
entry.save()
def unpause(self, date=None):
print('Unpause Hit')
if self.is_paused:
if not date:
date = timezone.now()
delta = date - self.pause_time
self.seconds_paused += delta.seconds
self.pause_time = None
def toggle_paused(self):
"""
Toggle the paused state of this entry. If the entry is already paused,
it will be unpaused; if it is not paused, it will be paused.
"""
print('Toggle Pause Hit')
if self.is_paused:
self.unpause()
else:
self.pause()
def check_overlap(self, entry_b, **kwargs):
"""Return True if the two entries overlap."""
consider_pause = kwargs.get('pause', True)
entry_a = self
# if entries are open, consider them to be closed right now
if not entry_a.end_time or not entry_b.end_time:
return False
# Check the two entries against each other
start_inside = entry_a.start_time > entry_b.start_time \
and entry_a.start_time < entry_b.end_time
end_inside = entry_a.end_time > entry_b.start_time \
and entry_a.end_time < entry_b.end_time
a_is_inside = entry_a.start_time > entry_b.start_time \
and entry_a.end_time < entry_b.end_time
b_is_inside = entry_a.start_time < entry_b.start_time \
and entry_a.end_time > entry_b.end_time
overlap = start_inside or end_inside or a_is_inside or b_is_inside
if not consider_pause:
return overlap
else:
if overlap:
max_end = max(entry_a.end_time, entry_b.end_time)
min_start = min(entry_a.start_time, entry_b.start_time)
diff = max_end - min_start
diff = diff.seconds + diff.days * 86400
total = entry_a.get_total_seconds() + entry_b.get_total_seconds() - 1
if total >= diff:
return True
return False
def is_overlapping(self):
if self.start_time and self.end_time:
entries = self.user.timepiece_entries.filter(
Q(end_time__range=(self.start_time, self.end_time)) |
Q(start_time__range=(self.start_time, self.end_time)) |
Q(start_time__lte=self.start_time, end_time__gte=self.end_time)
)
totals = entries.aggregate(max=Max('end_time'), min=Min('start_time'))
totals['total'] = 0
for entry in entries:
totals['total'] = totals['total'] + entry.get_total_seconds()
totals['diff'] = totals['max'] - totals['min']
totals['diff'] = totals['diff'].seconds + \
totals['diff'].days * 86400
if totals['total'] > totals['diff']:
return True
else:
return False
else:
return None
def save(self, *args, **kwargs):
self.hours = Decimal('%.5f' % round(self.total_hours, 5))
super(Entry, self).save(*args, **kwargs)
def get_total_seconds(self):
"""
Determines the total number of seconds between the starting and
ending times of this entry. If the entry is paused, the end_time is
assumed to be the pause time. If the entry is active but not paused,
the end_time is assumed to be now.
"""
start = self.start_time
end = self.end_time
if not end:
if self.is_paused:
end = self.pause_time
print(end)
print('------------------')
else:
end = timezone.now()
delta = end - start
if self.is_paused:
# get_paused_seconds() takes elapsed time into account, which we do not want
# in this case, so subtract seconds_paused instead to account for previous pauses
seconds = delta.seconds - self.seconds_paused
else:
seconds = delta.seconds - self.get_paused_seconds()
return seconds + (delta.days * 86400)
I know the error is comming from the method get_total_seconds(). When self.start_time is called it returns Entry object (None). How can I pass entryIdNum or entryId from views to the model so it knows what self is?
I am required to write a class involving dates. I am supposed to overload the + operator to allow days being added to dates. To explain how it works: A Date object is represented as (2016, 4, 15) in the format (year, month, date). Adding integer 10 to this should yield (2016, 4, 25). The Date class has values self.year, self.month, self.day.
My problem is that the code is supposed to work in the form Date + 10 as well as 10 + Date. Also Date - 1 should work in the sense of adding a negative number of days. Date(2016, 4, 25) - 1 returns Date(2016, 4, 24).
My code works perfectly in the form of Date + 10 but not in the form 10 + D or D - 1.
def __add__(self,value):
if type(self) != int and type(self) != Date or (type(value) != int and type(value) != Date):
raise TypeError
if type(self) == Date:
day = self.day
month = self.month
year = self.year
value = value
if type(value) != int:
raise TypeError
days_to_add = value
while days_to_add > 0:
day+=1
if day == Date.days_in(year,month):
month+=1
if month > 12:
day = 0
month = 1
year+=1
day = 0
days_to_add -=1
return(Date(year,month,day))
These are the errors I get
TypeError: unsupported operand type(s) for +: 'int' and 'Date'
TypeError: unsupported operand type(s) for -: 'Date' and 'int'
__radd__ handles right side addition so you need to implement that as well.
I am seeing some flaws in your implementation so I recommend you using datetime module (especially datetime.timedelta class) to at least handle basic date arithmetic correctly:
import datetime
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def as_date(self):
return datetime.date(self.year, self.month, self.day)
def __add__(self, other):
if isinstance(other, int):
date = self.as_date() + datetime.timedelta(days=other)
return Date(date.year, date.month, date.day)
else:
raise ValueError("int value is required")
def __radd__(self, other):
return self.__add__(other)
def __sub__(self, other):
return self.__add__(-other)
def __rsub__(self, other):
raise RuntimeError("Doesn't make sense.")
def __repr__(self):
return str(self.as_date())
Demo:
>>> date = Date(2015, 10, 23)
>>> print date + 10 # __add__ is called
2015-11-02
>>> print 20 + date # __radd__ is called
2015-11-12
>>> print date - 25 # __sub__ is called
2015-09-28
>>> print 25 - date # __rsub__ is called
RuntimeError: Doesn't make sense