Last active
December 26, 2025 20:00
-
-
Save devdattaT/c9dcae2107622215ff2e798dd185087e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) |
@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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.