def approx_date_diff(start, end, mode="e", as_years=False): """ A tag for transforming approximate dates into actual dates """ if not end: end = datetime.date.today() elif not hasattr(end, 'date'): print end.split('-') end = ApproximateDate(*map(int, end.split('-'))).date(mode) if not start: start = datetime.date.today() elif not hasattr(start, 'date'): print "s", start print start.split('-') start = ApproximateDate(*map(int, start.split('-'))).date(mode) days = (end - start).days if as_years: days_to_years(days) else: return days
def approx_date_diff(start,end,mode="e",as_years=False): """ A tag for transforming approximate dates into actual dates """ if not end: end = datetime.date.today() elif not hasattr(end,'date'): print end.split('-') end = ApproximateDate(*map(int,end.split('-'))).date(mode) if not start: start = datetime.date.today() elif not hasattr(start,'date'): print "s", start print start.split('-') start = ApproximateDate(*map(int,start.split('-'))).date(mode) days = (end - start).days if as_years: days_to_years(days) else: return days
def events_api(request): aggregators = request.GET.getlist('aggregator',['chamber__title']) filters = request.GET.getlist('filter',[]) since = request.GET.get('since',None) min_agg = request.GET.get('min',None) smooth = request.GET.get('smooth',False) is not False #samples only at start of service check_dates = request.GET.get('check_dates',False) is not False #and smooth # only do extra date checking if smooth otherwise this will thrash the DB show_totals = request.GET.get('totals',False) is not False fils = {} for f in filters: fil,val = f.split('|') fils[fil]=val event_type = models.Service.objects if since: since = ApproximateDate(*map(int,since.split('-'))).early() #events = event_type.filter(Q(end_date__gt=since)|Q(end_date='')).filter(**fils) # Pre-filter the events to look at events = event_type.filter(**fils) # Pre-filter the events to look at from datetime import timedelta, date available_keys = [] candidate_keys = events.values(*aggregators).order_by().distinct() if min_agg: candidate_keys = candidate_keys.annotate(count=Count('person')) totals = {} ds = key_dates = {} for k in candidate_keys: if min_agg: l = [k[agg] for agg in aggregators if k[agg] is not None and k['count'] > int(min_agg)] else: l = [k[agg] for agg in aggregators if k[agg] is not None] if l: k = '-'.join(l) ds[k]={'keys':l,'data':{}} # set up whole date structure here available_keys.append(k) def get_date_data_for_query(query,query_date): # We call this in two places and only within this function, and it needs to modify a ton of local stuff # So a local function with 2 arguments is a better pattern than a module function with the 7 or so arguments. membership_aggs = [a for a in aggregators if "membership" in a] if check_dates and membership_aggs: for a in membership_aggs: f=a.split("membership",1)[0]+'membership' # Get just the membership part query &= Q(**{f+'__start_date__lte':query_date}) query &= (Q(**{f+'__end_date__gte':query_date}) | Q(**{f+'__end_date__isnull':True})) val = events.filter(query).values(*aggregators).order_by().distinct().annotate(*[Count(a) for a in aggregators]) #print val for k in ds.keys(): ds[k]['data'][str(query_date)] = 0 for v in val: agg_var = "-".join([str(v[x]) for x in aggregators]) if agg_var in ds.keys(): ds[agg_var]['data'][str(query_date)] = int(v[aggregators[0]+'__count']) if show_totals: total = events.filter(query).count() totals[str(query_date)] = total for e in events.order_by("start_date"): dates = [e.start_date,e.end_date] if smooth: dates = [e.start_date] for event_date in dates: if event_date: day_after = event_date + timedelta(days=1) days = [day_after] if not smooth: day_before = event_date - timedelta(days=1) days = [day_before,day_after] for query_date in days: if not since or query_date > since: query = Q(start_date__lte=query_date) & (Q(end_date__gt= query_date) | Q(end_date__isnull=True)) #get_date_data_for_query(key_dates,events,query,query_date,aggregators,available_keys) get_date_data_for_query(query,query_date) today = date.today() if today not in key_dates.keys(): query = Q(end_date__isnull=True) #get_date_data_for_query(key_dates,events,query,today,aggregators,available_keys) get_date_data_for_query(query,today) # sort the dates properly keys = [] for agg,struct in key_dates.items(): d = struct['data'] struct['data'] = OrderedDict(sorted(d.items(), key=lambda t: t[0])) output = {'metadata':[],'data':key_dates} if show_totals: output['totals'] = totals return output