def modify(self, daterange): if isinstance(daterange, DaterangeAtom): by_days = daterange.split(u'days') if self.direction == 1: return [(day[0] + self.modification, utils.end_of_day(day[0])) for day in by_days] elif self.direction == -1: return [(day[0], day[0]+self.modification) for day in by_days] else: raise ValueError(u'daterange must be a subclass of DaterangeAtom')
def split(self, split_on=u'days'): """ Convenience function that allows a DateRange to be split into a list of single days.""" # Map split on string to a recurrence rule. split_on_rules = {u'days': rrule.DAILY, u'weeks': rrule.WEEKLY, u'months': rrule.MONTHLY} # If there is a valid rule return a split date range. rule = split_on_rules.get(split_on) if rule: splits = list(rrule.rrule(rule, count=((self.end - utils.start_of_day(self.start)).days), dtstart=self.start, until=self.end)) return [(s, utils.end_of_day(s)) for s in splits] else: raise ValueError(u'split_on value not supported.')
def __from_match(self, match, src_time, parse_type=u'range'): """ Initialize the instance given a plaintext match string.""" seed_dt = utils.safe_parsedatetime_first_nlp(match, src_time).get(u'datetime') if seed_dt: if parse_type == u'range': start = utils.start_of_day(seed_dt) end = utils.end_of_day(seed_dt) elif parse_type == u'exact': start = seed_dt end = seed_dt + datetime.timedelta(seconds=0) else: raise ValueError(u'Invalid value for parse_type. Try "range" or "exact"') # The special case in which an entire month is specified and not a specific date during it. if not re.search('[0-9]', match) and start.day == 1 and u'day' not in match: end = utils.end_of_month(seed_dt) DaterangeAtom.__init__(self, start, end, match, src_time) else: raise ValueError(u'CalendarDateRangeAtom cannot parse and intialized from given match value = '\ + unicode(match))
def determine_home_work_places(user_id, nb_days=3, hour_threshold=3): home_hours = [(0, 7), (20, 23)] work_hours = [(9, 18)] home_threshold = 60 * 60 * hour_threshold * nb_days # 4 hour threshold default work_threshold = 0 places = {} # get all the days # compute the unique places visited and the time spend at these places days = [] day = utils.previous_day(utils.today_string()) for i in range(nb_days): days.append(day) day = utils.previous_day(day) for day in days: weekend = utils.is_weekend(day) visits = user_traces_db.load_user_visits_utc(user_id, day) if len(visits) == 0: return None, None if not weekend: work_threshold += 60 * 60 * hour_threshold # fix the last visit last_visit = visits[-1] utc_offset = last_visit['d_utc'] if not utc_offset: return None, None last_visit_end = last_visit['d'] - utc_offset # departure_utc - utc_offset last_visit_end = utils.end_of_day(last_visit_end) visits[-1]['d'] = last_visit_end + utc_offset for visit in visits: start = max(utils.start_of_day_str(day), visit['a'] - visit['d_utc']) # arrival_utc and utc_offset end = visit['d'] - visit['d_utc'] # departure_utc and utc_offset place_id = visit['pid'] # place = user_traces_db.load_user_place(user_id, place_id) # print("%s [%s %s -> %s %s] %s" % (day, utils.timestamp_to_day_str(start), utils.hm(start), utils.timestamp_to_day_str(end), utils.hm(end), place['name'])) work_seconds = 0 if not weekend: work_seconds = utils.seconds_in_hour_range(start, end, work_hours) home_seconds = utils.seconds_in_hour_range(start, end, home_hours) if place_id not in places: places[place_id] = [0, 0] places[place_id] = map(add, places[place_id], [home_seconds, work_seconds]) new_places = {} for pid, p in places.items(): new_places[pid] = list(p) # Determine the work and home places home_place = None home_places = [(pid, p[0]) for pid, p in new_places.items() if p[0] > home_threshold] if len(home_places): home_place = max(home_places, key=lambda x: x[1]) # can have multiple work locations work_places = [pid for pid, p in new_places.items() if p[1] > work_threshold] return home_place[0] if home_place else None, work_places