def to_time_string(state, datetime_obj): """ Converts python datetime object to a string to be displayed on front end. Compares to today's date in order to display "Today" or "Tomorrow". Timezone to get today's date is computed using the state the ride departs from. """ tz = state_to_timezone(state) today = datetime.now(pytz.timezone(tz)).date() if datetime_obj.date() == today: datetime_str = "Today, {}".format(datetime_obj.strftime('%-I:%M %p')) # If ride is tomorrow, adjust attribute to indicate elif datetime_obj.date() == (today + timedelta(days=1)): datetime_str = "Tomorrow, {}".format( datetime_obj.strftime('%-I:%M %p')) # Otherwise change attribute to formatted timestamp string else: datetime_str = datetime_obj.strftime('%A, %b %d, %Y %-I:%M %p') return datetime_str
def to_local(state, datetime_obj): """ Convert timestamp from database to local time. First converts to tz-aware UTC, then to local time given the rides starting state. """ # Use state from database to determine timezone tz = state_to_timezone(state) # Convert timestamp from db to be aware that it is in utc utc = datetime_obj.replace(tzinfo=pytz.utc) # Convert start_timestamp attribute to timezone of state local = pytz.timezone(tz).normalize(utc) return local
def to_utc(state, datetime_obj): """ Takes in unaware python datetime object, converts to tz aware, then converts to UTC. """ # Get timezone of starting state or user's state tz = state_to_timezone(state) # Localize to timezone of state the ride is leaving from datetime_aware = pytz.timezone(tz).localize(datetime_obj) # Normalize to UTC in order to search DB datetime_utc = pytz.utc.normalize(datetime_aware) return datetime_utc
def to_utc_db_time(state, datetime_obj): """ Takes in unaware python datetime object, converts to tz aware, adding 8hour offset, then converts to UTC. """ # Get timezone of starting state or user's state tz = state_to_timezone(state) # Localize to timezone of state the ride is leaving from datetime_aware = pytz.timezone(tz).localize(datetime_obj) utc_offset = datetime_aware.utcoffset().total_seconds() / 60 / 60 datetime_aware = datetime_aware + timedelta(hours=utc_offset) # Normalize to UTC in order to search DB datetime_utc = pytz.utc.normalize(datetime_aware) return datetime_utc
def search_rides(): """Searches database for rides""" # initialize to show 10 results ordered by date limit = 10 cost = 50 order_by = 'date' ### If user clicks 'All Rides' ### if request.args.get('query'): # Defaulting to the starting toggle points when viewing all rides state = '' start_time = datetime.strptime("12:00 AM", '%I:%M %p') start_time = datetime.combine(datetime.now().date(), start_time.time()) start_time = to_utc(state, start_time).time() date_from = to_utc(state, datetime.now()).date() # Query database for all rides rides = Ride.get_rides(start_time=start_time, date_from=date_from, cost=cost, limit=limit, order_by=order_by) total_count = Ride.get_rides(start_time=start_time, date_from=date_from, cost=cost, order_by=order_by, count=True) # Round up page count with + 1 page_count = int(math.ceil(float(total_count) / float(limit))) for ride in rides: # convert ride to local timezone ride.start_timestamp = to_local(ride.start_state, ride.start_timestamp) # turn date object into string for front end ride.start_timestamp = to_time_string(ride.start_state, ride.start_timestamp) # Render search page, passing rides and page_count for pagination return render_template('search.html', rides=rides, page_count=page_count) ### If user enters search terms ### else: # Start with 15mile square search miles = 25 deg = miles_to_degrees(miles) # Get search terms lat/lng start_lat = request.args.get('lat') start_lng = request.args.get('lng') end_lat = request.args.get('lat2') end_lng = request.args.get('lng2') if not start_lat or not start_lng: start_lat = 0.0 start_lng = 0.0 else: start_lat = float(start_lat) start_lng = float(start_lng) if not end_lat or not end_lng: end_lat = 0.0 end_lng = 0.0 else: end_lat = float(end_lat) end_lng = float(end_lng) # Dicts holding search terms to be placed in DOM and used by AJAX when # user toggles search parameters start_search = { "term": request.args.get('searchstring', ''), "state": request.args.get('administrative_area_level_1', ''), "lat": start_lat, "lng": start_lng } end_search = { "term": request.args.get('searchstring2', ''), "state": request.args.get('administrative_area_level_1_2', ''), "lat": end_lat, "lng": end_lng } state = start_search['state'] if not state_to_timezone(state): state = '' start_time = datetime.strptime("12:00 AM", '%I:%M %p') start_time = datetime.combine(datetime.now().date(), start_time.time()) start_time = to_utc(state, start_time).time() date_from = to_utc(state, datetime.now()).date() # Get the first 10 results for query rides = Ride.get_rides(deg=deg, start_lat=start_lat, start_lng=start_lng, end_lat=end_lat, end_lng=end_lng, limit=limit, start_time=start_time, date_from=date_from, order_by=order_by) if len(rides) > limit: total_count = Ride.get_rides(deg=deg, start_lat=start_lat, start_lng=start_lng, end_lat=end_lat, end_lng=end_lng, limit=limit, start_time=start_time, date_from=date_from, order_by=order_by, count=True) # Round up page count with + 1 page_count = int(math.ceil(float(total_count) / float(limit))) else: page_count = 1 for ride in rides: # convert ride to local timezone ride.start_timestamp = to_local(ride.start_state, ride.start_timestamp) # turn date object into string for front end ride.start_timestamp = to_time_string(ride.start_state, ride.start_timestamp) return render_template('search.html', rides=rides, start_search=start_search, end_search=end_search, page_count=page_count)
def json_test(): """Return new ride results""" #Get search terms start_term = request.args.get('start_term') end_term = request.args.get('end_term') user_lat = request.args.get('user_lat') user_lng = request.args.get('user_lng') start_lat = request.args.get('start_lat') start_lng = request.args.get('start_lng') end_lat = request.args.get('end_lat') end_lng = request.args.get('end_lng') start_state = request.args.get("start_state") # Get search toggles (time, cost, date) start_time = request.args.get("start") cost = request.args.get("cost") date_from = request.args.get("date_from") date_to = request.args.get("date_to") limit = request.args.get("limit") offset = request.args.get("offset") offset = int(offset) * int(limit) order_by = request.args.get("order") # If there are no search terms, start_state will be an empty string. In this # case it it best to use the clients timezone to cater results to dates/ times in their # tz. if not start_state: # Using a try statement, because if google is unable to geocode the user, # I don't want this to error out, any would rather default to 'US/Pacific' try: start_state = (geocoder.google('{}, {}'.format(user_lat, user_lng))).state # adding this check, because sometimes this returns odd strings if len(start_state) > 2: start_state = '' except: # Blank start states default to 'US/Pacific' start_state = '' if not state_to_timezone(start_state): start_state = '' # convert dates and time to utc to be queried against db if date_from: date_from = datetime.strptime(date_from, '%m/%d/%Y') date_from = to_utc(start_state, date_from).date() if date_to: date_to = datetime.strptime(date_to, '%m/%d/%Y') date_to = to_utc(start_state, date_to).date() start_time = datetime.strptime(start_time, '%I:%M %p') start_time = datetime.combine(datetime.now().date(), start_time.time()) start_time = to_utc(start_state, start_time).time() print '\n\n*******\n{}\n****\n\n'.format(start_time) # Convert miles to lat/lng degrees deg = miles_to_degrees(25) rides = Ride.get_rides(deg=deg, start_lat=start_lat, start_lng=start_lng, end_lat=end_lat, end_lng=end_lng, start_time=start_time, cost=cost, date_to=date_to, date_from=date_from, limit=limit, offset=offset, order_by=order_by) print '\nlimit: {}\noffset: {}\norder_by: {}\ndate_from: {}\nstart_time: {}\ncost: {}'.format( limit, offset, order_by, date_from, start_time, cost) total_count = Ride.get_rides(deg=deg, start_lat=start_lat, start_lng=start_lng, end_lat=end_lat, end_lng=end_lng, start_time=start_time, cost=cost, date_to=date_to, date_from=date_from, count=True) print '\ntotal_count: {}\n'.format(total_count) json_list = sqlalchemy_to_json(rides, total_count, limit) return jsonify(json_list)
def all_data(): """Create some sample data.""" # In case this is run more than once, empty out existing data print "deleting data" db.drop_all() db.create_all() # Add sample employees and departments with open('seed-data/users_seed.csv', 'rb') as ride_data: reader = csv.reader(ride_data, quotechar="'", delimiter=',', quoting=csv.QUOTE_ALL, skipinitialspace=True) reader.next() for row in reader: user = User(user_id=row[0], fb_userid=row[1], first_name=row[2], last_name=row[3], email=row[4], image=row[5]) db.session.add(user) db.session.commit() with open('seed-data/rides_seed.csv', 'rb') as ride_data: reader = csv.reader(ride_data, quotechar="'", delimiter=',', quoting=csv.QUOTE_ALL, skipinitialspace=True) reader.next() gmaps = googlemaps.Client(key=GOOGLE_KEY) geocode = defaultdict(defaultdict) for row in reader: route = row[15] if not geocode[route]: start_lat = row[3] start_lng = row[4] end_lat = row[5] end_lng = row[6] time.sleep(1) g_start = geocoder.google('{}, {}'.format( start_lat, start_lng)) time.sleep(1) g_end = geocoder.google('{}, {}'.format(end_lat, end_lng)) geocode[route]['start_lat'] = start_lat geocode[route]['start_lng'] = start_lng geocode[route]['start_number'] = g_start.housenumber geocode[route]['start_street'] = g_start.street geocode[route]['start_city'] = g_start.city geocode[route]['start_state'] = g_start.state geocode[route]['start_zip'] = g_start.postal geocode[route]['end_lat'] = end_lat geocode[route]['end_lng'] = end_lng geocode[route]['end_number'] = g_end.housenumber geocode[route]['end_street'] = g_end.street geocode[route]['end_city'] = g_end.city geocode[route]['end_state'] = g_end.state geocode[route]['end_zip'] = g_end.postal start_time = datetime.strptime('4:00 PM', '%I:%M %p') today = datetime.now().date() start_datetime = datetime.combine( datetime.now().date() + timedelta(days=1), start_time.time()) tz = state_to_timezone(geocode[route]['start_state']) start_time_aware = pytz.timezone(tz).localize(start_datetime) try: directions_result = gmaps.directions( "{},{}".format(start_lat, start_lng), "{},{}".format(end_lat, end_lng), traffic_model='best_guess', departure_time=start_time_aware) geocode[route]['duration'] = directions_result[0]['legs'][ 0]['duration']['text'] geocode[route]['mileage'] = directions_result[0]['legs'][ 0]['distance']['text'] print '\n\nduration: {}, mileage{}\n\n'.format( geocode[route]['duration'], geocode[route]['mileage']) except Exception, e: print '\n\nDuration/Mileage API Failed\n\n' geocode[route]['mileage'] = None geocode[route]['duration'] = None print "Unexpected error:", start_lat, start_lng, end_lat, end_lng print str(e) start_time = datetime.strptime(row[7], '%I:%M %p') today = datetime.now().date() day_offset = int(row[14]) start_datetime = datetime.combine( datetime.now().date() + timedelta(days=day_offset), start_time.time()) tz = state_to_timezone(geocode[route]['start_state']) # localize to US/Pacific start_time_aware = pytz.timezone(tz).localize(start_datetime) # Normalize to UTC start_time_utc = pytz.utc.normalize(start_time_aware) ride = Ride( driver=row[0], seats=row[1], cost=row[2], # Start Location start_lat=geocode[route]['start_lat'], start_lng=geocode[route]['start_lng'], start_number=geocode[route]['start_number'], start_street=geocode[route]['start_street'], start_city=geocode[route]['start_city'], start_state=geocode[route]['start_state'], start_zip=geocode[route]['start_zip'], # End Location end_lat=geocode[route]['end_lat'], end_lng=geocode[route]['end_lng'], end_number=geocode[route]['end_number'], end_street=geocode[route]['end_street'], end_city=geocode[route]['end_city'], end_state=geocode[route]['end_state'], end_zip=geocode[route]['end_zip'], # Date/Time start_timestamp=start_time_utc, #Details car_type=row[9], luggage=row[10], comments=row[11], pickup_window=row[12], detour=row[13], mileage=geocode[route]['mileage'], duration=geocode[route]['duration']) db.session.add(ride) db.session.commit() print geocode
def test_state_to_timezone2(self): self.assertEqual(state_to_timezone(''), 'US/Pacific')
def test_state_to_timezone(self): self.assertEqual(state_to_timezone('NY'), 'US/Eastern')