Skip to content

Instantly share code, notes, and snippets.

@lena
Last active September 11, 2018 13:35
Show Gist options
  • Save lena/43a8bd5b6acca810de337509cdd0c5b6 to your computer and use it in GitHub Desktop.
Save lena/43a8bd5b6acca810de337509cdd0c5b6 to your computer and use it in GitHub Desktop.
Solution to Onboarding Project #2
"""
Location to Datetime CLI
Usage:
python location_to_datetime.py --coordinates='39.6034810,-119.6822510'
python location_to_datetime.py --address='278 Bay Ridge Avenue, Brooklyn, NY, 11209'
python location_to_datetime.py --address='New York' --from-time='2017-08-08' --from-address='Egypt'
python location_to_datetime.py --address='New York' --from-time='2017-08-08T10:20:23' --from-address='Egypt'
python location_to_datetime.py --address='New York' --to-json
python location_to_datetime.py --address='New York' --format-str='YYYY-MM-DD HH:mm:ss ZZ'
Note:
Because there is no API key configured, the Google API sometimes returns an error instead of the correct result.
So just retry. This can be fixed by adding a `&key=<API_KEY>` to the API requests.
"""
import sys
import json
import argparse
import datetime
import requests
import arrow
GOOGLE_TIMEZONE_API_URL = 'https://maps.googleapis.com/maps/api/timezone/json'
GOOGLE_ADDRESS_API_URL = 'https://maps.googleapis.com/maps/api/geocode/json'
def run(coordinates=None, address=None, from_address=None, from_time=None):
assert (coordinates or address), 'Must provide an address or coordinates value to get a result.'
assert (from_address and from_time) or (not from_address and not from_time), 'Must provide a from_address and from_time value if you want to convert a datetime.'
if coordinates:
try:
tz = _get_timezone_for_coordinates(coordinates)
except Exception:
raise Exception('Could not find timezone for provided coordinates')
else:
try:
tz = _get_timezone_for_address(address)
except Exception:
raise Exception('Could not find timezone for provided address')
if not from_address and not from_time:
result = arrow.now(tz)
else:
try:
result = _convert_timezone(tz, from_address, from_time)
except Exception:
raise Exception('Could not find timezone for provided from_address')
return result
def _convert_timezone(tz, from_address, from_time):
from_tz = _get_timezone_for_address(from_address)
from_datetime = datetime.datetime.fromisoformat(from_time)
return arrow.get(from_datetime, from_tz).to(tz)
def _datetime_to_json(dt):
obj = {
'year': dt.year,
'month': dt.month,
'day': dt.day,
'hour': dt.hour,
'minute': dt.minute,
'timezone': dt.strftime('%Z')
}
return json.dumps(obj)
def _get_timezone_for_coordinates(coordinates):
response = requests.get('{}?location={}&timestamp=100'.format(GOOGLE_TIMEZONE_API_URL, coordinates))
return response.json()['timeZoneId']
def _get_timezone_for_address(address):
response = requests.get('{}?address={}'.format(GOOGLE_ADDRESS_API_URL, address))
location = response.json()['results'][0]['geometry']['location']
coordinates = ('{lat},{lng}'.format(**location))
return _get_timezone_for_coordinates(coordinates)
def _format_result(result, to_json, format_str):
if to_json:
return _datetime_to_json(result)
if format_str:
return result.format(format_str)
return result.isoformat()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Returns the requested location\'s current time or converts timezones.')
parser.add_argument('--from-address', type=str, help='Address that you want to convert from, e.g., \'Egypt\'')
parser.add_argument('--from-time', type=str, help='Date/datetime (in ISO8601 format) that you want to convert.')
location_group = parser.add_mutually_exclusive_group()
location_group.add_argument('--coordinates', help='Coordinates string you want to look up the time for, e.g., \'39.6034810,-119.6822510\'')
location_group.add_argument('--address', type=str, help='Address you want to look up the time for, e.g., \'New York\'.')
result_format_group = parser.add_mutually_exclusive_group()
result_format_group.add_argument('--to-json', help='True if you want the result to be a json date object', action='store_true')
result_format_group.add_argument('--format-str', type=str, help='Specify a format of the result string.')
args = parser.parse_args()
print(args)
try:
result = run(
coordinates=args.coordinates,
address=args.address,
from_address=args.from_address,
from_time=args.from_time,
)
formatted_result = _format_result(result, args.to_json, args.format_str)
print(formatted_result)
except Exception as e:
print(e, file=sys.stderr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment