from datetime import date, datetime, time, timedelta from django.db.models import Q, F from django.views.generic import TemplateView from sncfgtfs.models import Stop, StopTime, CalendarDate, Calendar class GareView(TemplateView): template_name = "sncfgtfs/gare.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) stop = Stop.objects.filter(name__iexact=kwargs["gare"], location_type=1).first() context['stop'] = stop next_departures = [] now = datetime.now() if self.request.GET.get('date', None): query_date = date.fromisoformat(self.request.GET['date']) else: query_date = now.date() if self.request.GET.get('time', None): query_time = time.fromisoformat(self.request.GET['time']) else: query_time = now.time() context['query_date'] = query_date context['query_time'] = query_time query_time = query_time.isoformat(timespec='seconds') query_time = timedelta(seconds=int(query_time[:2]) * 3600 + int(query_time[3:5]) * 60 + int(query_time[6:])) yesterday = query_date - timedelta(days=1) time_yesterday = query_time + timedelta(days=1) tomorrow = query_date + timedelta(days=1) qs = StopTime.objects.annotate(departure_time_24h=F('departure_time')).none() for child in Stop.objects.filter(name__iexact=kwargs["gare"], location_type=0).all(): qs_child = StopTime.objects.filter(stop=child, pickup_type=0) qs_child_tod = qs_child.filter(Q(departure_time__gte=query_time) & (Q(trip__service_id__in=CalendarDate.objects.filter( date=query_date, exception_type=1).values_list('service_id')) | Q(trip__service_id__in=Calendar.objects.filter( start_date__lte=query_date, end_date__gte=query_date, **{f"{query_date:%A}".lower(): True}) .filter(~Q(id__in=CalendarDate.objects.filter( date=query_date, exception_type=2) .values_list('service_id'))) .values_list('id')))) \ .annotate(departure_time_24h=F('departure_time')) qs_child_yes = qs_child.filter(Q(departure_time__gte=time_yesterday) & (Q(trip__service_id__in=CalendarDate.objects.filter( date=yesterday, exception_type=1).values_list('service_id')) | Q(trip__service_id__in=Calendar.objects.filter( start_date__lte=yesterday, end_date__gte=yesterday, **{f"{yesterday:%A}".lower(): True}) .filter(~Q(id__in=CalendarDate.objects.filter( date=yesterday, exception_type=2) .values_list('service_id'))) .values_list('id')))) \ .annotate(departure_time_24h=F('departure_time') - timedelta(days=1)) qs_child_tom = qs_child.filter(Q(departure_time__gte=timedelta(0)) & (Q(trip__service_id__in=CalendarDate.objects.filter( date=tomorrow, exception_type=1).values_list('service_id')) | Q(trip__service_id__in=Calendar.objects.filter( start_date__lte=tomorrow, end_date__gte=tomorrow, **{f"{tomorrow:%A}".lower(): True}) .filter(~Q(id__in=CalendarDate.objects.filter( date=tomorrow, exception_type=2) .values_list('service_id'))) .values_list('id')))) \ .annotate(departure_time_24h=F('departure_time') + timedelta(days=1)) qs_child = qs_child_tod.union(qs_child_yes).union(qs_child_tom) qs = qs.union(qs_child) next_departures += qs.order_by("departure_time_24h")[:20].all() context['next_departures'] = next_departures return context