-
-
Save devdattaT/c9dcae2107622215ff2e798dd185087e to your computer and use it in GitHub Desktop.
| import json | |
| import csv | |
| import sys | |
| from datetime import datetime | |
| import os | |
| def has_keys(dictionary, keys): | |
| return all(key in dictionary for key in keys) | |
| def make_reader(in_json): | |
| # Open location history data | |
| json_data = json.loads(open(in_json).read()) | |
| #Will read the following keys | |
| keys_to_check = ['timestamp', 'longitudeE7', 'latitudeE7', 'accuracy'] | |
| # Get the easy fields | |
| for item in json_data['locations']: | |
| if has_keys(item, keys_to_check): | |
| timestamp = item['timestamp'] | |
| if ('.' in timestamp): | |
| date = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ').date() | |
| else: | |
| date = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ').date() | |
| tm = timestamp.split('T')[1].split('Z')[0] | |
| longitude = item['longitudeE7']/10000000.0 | |
| latitude = item['latitudeE7']/10000000.0 | |
| accuracy = item['accuracy'] | |
| yield [date, tm, longitude, latitude, accuracy] | |
| 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 | |
| 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(['Date', 'Time', 'Longitude', 'Latitude', 'Accuracy']) | |
| print("Reading {0}".format(in_file)) | |
| reader = make_reader(in_file) | |
| for r in reader: | |
| features.append(r) | |
| print('Read {0} Records'.format(len(features)-1)) | |
| # write this data | |
| with open(out_file, 'w', newline='')as f: | |
| writer = csv.writer(f) | |
| writer.writerows(features) |
As of Dec 31, 2024 location timeline export on Android - the JSON data format has changed and needs a chance in make_reader() function, which I added to my fork. Please free to pull it to sync if needed. Thanks for bootstrapping this script.
@sitz I tried to run your code but I get a KeyError: 'semanticSegments'.
This one can make GPX-Files (one GPX-File per day) https://github.com/Makeshit/Timeline-GPX-Exporter
@dinilj007 - I do a decent amount of python coding but for small things like this I use GPT also. Yours didn't work for my timeline export, so I fed GPT a sample of some of mine, followed by your script and the error message and it gave me a working script. Took less than 2 mins, which is why I didn't figure it out myself haha:
import json import csv from datetime import datetime import os def make_reader(in_json): # Open location history data with open(in_json, 'r') as file: json_data = json.load(file) # Access the "semanticSegments" list segments = json_data.get("semanticSegments", []) for segment in segments: start_time = segment.get('startTime', 'Unknown') end_time = segment.get('endTime', 'Unknown') # Process the start and end times if start_time != 'Unknown': if '.' in start_time: start_date = datetime.strptime(start_time, '%Y-%m-%dT%H:%M:%S.%f%z').date() else: start_date = datetime.strptime(start_time, '%Y-%m-%dT%H:%M:%S%z').date() start_tm = start_time.split('T')[1].split('-')[0] else: start_date = 'Unknown' start_tm = 'Unknown' if end_time != 'Unknown': if '.' in end_time: end_date = datetime.strptime(end_time, '%Y-%m-%dT%H:%M:%S.%f%z').date() else: end_date = datetime.strptime(end_time, '%Y-%m-%dT%H:%M:%S%z').date() end_tm = end_time.split('T')[1].split('-')[0] else: end_date = 'Unknown' end_tm = 'Unknown' # Extract location details from "visit" or "timelinePath" lat, lon = None, None if 'visit' in segment: placeLocation = segment['visit'].get('topCandidate', {}).get('placeLocation', {}).get('latLng', None) if placeLocation: lat, lon = [float(coord.strip('°')) for coord in placeLocation.split(", ")] elif 'timelinePath' in segment: # Extract the first point from timelinePath if it exists if len(segment['timelinePath']) > 0: point = segment['timelinePath'][0].get('point', None) if point: lat, lon = [float(coord.strip('°')) for coord in point.split(", ")] # Yield the extracted data yield [end_date, end_tm, start_date, start_tm, lat, lon] 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 # Hard-coded file paths in_file = 'input.json' # Replace with your input JSON file path out_file = 'output.csv' # Replace with your desired output CSV file path in_file = getFullPath(in_file) out_file = getFullPath(out_file) features = [] # add the Headers features.append(['End Date', 'End Time', 'Start Date', 'Start Time', 'Latitude', 'Longitude']) print("Reading {0}".format(in_file)) reader = make_reader(in_file) for r in reader: features.append(r) print('Read {0} Records'.format(len(features) - 1)) # write this data with open(out_file, 'w', newline='') as f: writer = csv.writer(f) writer.writerows(features)
nope, Chuck Testa
C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx>python ConvertGoogleHistory.py Timeline.json out.csv
Reading C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\input.json
Traceback (most recent call last):
File "C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\ConvertGoogleHistory.py", line 81, in <module>
for r in reader:
^^^^^^
File "C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\ConvertGoogleHistory.py", line 8, in make_reader
with open(in_json, 'r') as file:
~~~~^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Nutzer\\Documents\\Meine empfangenen Dateien\\xxxx\\input.json'
C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx>python ConvertGoogleHistory.py Timeline.json out.csv
Reading C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\input.json
Traceback (most recent call last):
File "C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\ConvertGoogleHistory.py", line 81, in <module>
for r in reader:
^^^^^^
File "C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx\ConvertGoogleHistory.py", line 54, in make_reader
lat, lon = [float(coord.strip('°')) for coord in point.split(", ")]
~~~~~^^^^^^^^^^^^^^^^^^
ValueError: could not convert string to float: '50.5277699Â'
C:\Users\Nutzer\Documents\Meine empfangenen Dateien\xxxx>```
doesn't work for me.
I hacked this together https://gist.github.com/epk/a70dd9b7a2d5bf8e5d86ebdcaefb6b32