-
-
Save dimisjim/173c78d01219bc767d1f373e48e6a28a to your computer and use it in GitHub Desktop.
#!/usr/bin/python3 | |
import json | |
import csv | |
import sys | |
import datetime | |
import os | |
def make_reader(in_json): | |
# Open location history data | |
with open(in_json) as f: | |
json_data = json.load(f) | |
print("JSON data loaded.") | |
# Process the JSON data | |
if 'timelineObjects' in json_data: | |
timeline_objects = json_data['timelineObjects'] | |
else: | |
print("Expected 'timelineObjects' in JSON data.") | |
return | |
# Process placeVisit entries | |
for item in timeline_objects: | |
if 'placeVisit' in item: | |
visit = item['placeVisit'] | |
location = visit['location'] | |
duration = visit['duration'] | |
try: | |
dt_start = datetime.datetime.strptime(duration['startTimestamp'], '%Y-%m-%dT%H:%M:%SZ') | |
except ValueError: | |
dt_start = datetime.datetime.strptime(duration['startTimestamp'], '%Y-%m-%dT%H:%M:%S.%fZ') | |
try: | |
dt_end = datetime.datetime.strptime(duration['endTimestamp'], '%Y-%m-%dT%H:%M:%SZ') | |
except ValueError: | |
dt_end = datetime.datetime.strptime(duration['endTimestamp'], '%Y-%m-%dT%H:%M:%S.%fZ') | |
longitude = location['longitudeE7'] / 10000000.0 | |
latitude = location['latitudeE7'] / 10000000.0 | |
place_id = location['placeId'] | |
address = location.get('address', 'N/A') | |
location_confidence = location.get('locationConfidence', 'N/A') | |
yield [dt_start, dt_start.strftime('%Y-%m-%d'), dt_start.strftime('%H:%M:%S'), | |
dt_end, dt_end.strftime('%Y-%m-%d'), dt_end.strftime('%H:%M:%S'), | |
longitude, latitude, place_id, address, location_confidence, 'N/A', 'N/A'] | |
# Process activitySegment entries | |
for item in timeline_objects: | |
if 'activitySegment' in item: | |
segment = item['activitySegment'] | |
start_location = segment['startLocation'] | |
end_location = segment['endLocation'] | |
duration = segment['duration'] | |
activity_type = segment['activityType'] | |
distance = segment.get('distance', 0) | |
try: | |
dt_start = datetime.datetime.strptime(duration['startTimestamp'], '%Y-%m-%dT%H:%M:%SZ') | |
except ValueError: | |
dt_start = datetime.datetime.strptime(duration['startTimestamp'], '%Y-%m-%dT%H:%M:%S.%fZ') | |
try: | |
dt_end = datetime.datetime.strptime(duration['endTimestamp'], '%Y-%m-%dT%H:%M:%SZ') | |
except ValueError: | |
dt_end = datetime.datetime.strptime(duration['endTimestamp'], '%Y-%m-%dT%H:%M:%S.%fZ') | |
start_longitude = start_location['longitudeE7'] / 10000000.0 | |
start_latitude = start_location['latitudeE7'] / 10000000.0 | |
end_longitude = end_location['longitudeE7'] / 10000000.0 | |
end_latitude = end_location['latitudeE7'] / 10000000.0 | |
yield [dt_start, dt_start.strftime('%Y-%m-%d'), dt_start.strftime('%H:%M:%S'), | |
dt_end, dt_end.strftime('%Y-%m-%d'), dt_end.strftime('%H:%M:%S'), | |
start_longitude, start_latitude, 'N/A', 'N/A', 'N/A', 'N/A', | |
end_longitude, end_latitude, activity_type, distance] | |
def getFullPath(inPath): | |
if not os.path.isabs(inPath): | |
# we need to set up the absolute path | |
script_path = os.path.abspath(__file__) | |
path, file = os.path.split(script_path) | |
inPath = os.path.join(path, inPath) | |
return inPath | |
# Read the Parameters | |
if len(sys.argv) < 3: | |
print("Usage: script.py <input_json_file> <output_csv_file>") | |
sys.exit(1) | |
in_file = sys.argv[1] | |
out_file = sys.argv[2] | |
in_file = getFullPath(in_file) | |
out_file = getFullPath(out_file) | |
features = [] | |
# add the Headers | |
features.append(['Start Datetime', 'Start Date', 'Start Time', 'End Datetime', 'End Date', 'End Time', | |
'Longitude', 'Latitude', 'Place ID', 'Address', 'Location Confidence', | |
'Start Longitude', 'Start Latitude', 'End Longitude', 'End Latitude', 'Activity Type', 'Distance']) | |
print("Reading {0}".format(in_file)) | |
reader = make_reader(in_file) | |
record_count = 0 | |
for r in reader: | |
print(r) # Print each record to see what is being processed | |
features.append(r) | |
record_count += 1 | |
print(f'Read {record_count} Records') | |
# write this data | |
with open(out_file, 'w', newline='') as f: | |
writer = csv.writer(f) | |
writer.writerows(features) | |
print(f'CSV output written to {out_file}') |
Works for me - for alexzmercury - basically you have to use a terminal shell window, and you need to have python3 installed - if you're not familiar with that it may be a bit of work but it isn't too hard. Then you download this above script into a file such as "convert.py" and then you can run it from your terminal shell with "python3 convert.py location-history.json myoutput.csv" ...
This should only work for the old timeline exports only, right? The ones exported with Takeout, which would include a JSON file for each month of the year, and would include the timelineObjects array, and then divide into placeVisit and activitySegment. However, the new timeline export through the Android Location settings has a very different JSON structure, showing semanticSegments and more than the two children types. How do we parse this new JSON to CSV?
Hello,
I needed to download my Google Maps location history, and having it in a .csv would make it a lot more accessible.
I have never used this sort of function; could you let me know via a walkthrough how I can run this so that I may export my files to .csv?