1616
1717import json
1818import numpy as np
19- import datetime
19+ import datetime as dt
20+ from datetime import datetime
2021
2122
2223# Helper functions
2324def date_ymd_to_timestamp_ms (y ,m ,d ):
24- return datetime .datetime (y ,m ,d ).timestamp ()* 1e3
25+ return dt .datetime (y ,m ,d ).timestamp ()* 1e3
2526
2627
2728def deg2rad (a ):
@@ -38,10 +39,17 @@ def dist_btw_two_points(p1,p2):
3839 r = 6371 * 1e3 # Earth's radius: 6371kms in meters
3940 return 2 * r * np .arcsin (np .sqrt (np .sin ((phi2 - phi1 )/ 2 )** 2 + np .cos (phi1 )* np .cos (phi2 )* np .sin ((lba2 - lba1 )/ 2 )** 2 ))
4041
42+ def parse_rfc3339 (datetime_str : str ) -> datetime :
43+ try :
44+ return datetime .strptime (datetime_str , "%Y-%m-%dT%H:%M:%S.%fZ" )
45+ except ValueError :
46+ # Perhaps the datetime has a whole number of seconds with no decimal
47+ # point. In that case, this will work:
48+ return datetime .strptime (datetime_str , "%Y-%m-%dT%H:%M:%SZ" )
4149
4250# LOAD DATA
4351
44- json_file = "location_history .json"
52+ json_file = "Records .json"
4553# Read the file
4654print ("Loading '%s' ..." % json_file )
4755main_dict = json .load (open (json_file )) # This can take a bit of time
@@ -63,15 +71,17 @@ def dist_btw_two_points(p1,p2):
6371
6472# Build arrays of basic data
6573print ("Extracting relevant data..." )
66- timestampMs = np .zeros ( n ) # in milliseconds
74+ timestamp = np .empty ( n , object ) # empty as timestamp has to be parsed first
6775positions = np .zeros ([n ,2 ]) # in degrees
6876accuracy = np .zeros (n ) # don't know the unit
6977# activity = {} # Don't store activity since we don't use it
7078
7179for i in range (n ):
7280 point = data [i ]
73- if 'timestampMs' in point :
74- timestampMs [i ] = float (point ['timestampMs' ])
81+ if 'timestamp' in point :
82+ timestamp [i ] = point ['timestamp' ]
83+ timestamp [i ] = parse_rfc3339 (timestamp [i ])
84+ timestamp [i ] = float (datetime .timestamp (timestamp [i ])* 1e3 )
7585 if ('latitudeE7' in point ) and ('longitudeE7' in point ):
7686 positions [i ] = np .array ([float (point ['latitudeE7' ]),float (point ['longitudeE7' ])])/ 1e7
7787 if 'accuracy' in point :
@@ -92,16 +102,16 @@ def dist_btw_two_points(p1,p2):
92102#############
93103
94104# Get first and last timestamps of interest
95- begin_ts = date_ymd_to_timestamp_ms (2018 , 9 ,1 )
96- end_ts = date_ymd_to_timestamp_ms (2018 , 9 , 30 )
97- # end_ts = timestampMs [-1] # Last one
105+ begin_ts = date_ymd_to_timestamp_ms (2013 , 12 ,1 )
106+ end_ts = date_ymd_to_timestamp_ms (2023 , 6 , 11 )
107+ # end_ts = timestamp [-1] # Last one
98108
99109# Point of interest
100- poi = np .array ([45.773944 , 4.890715 ]) # in degrees
110+ poi = np .array ([44.84176165939715 , - 0.5690463850963396 ]) # in degrees
101111radius_max = 50 # in meters
102112
103113# Define the interval of time below which timestamps should be grouped together
104- group_size = datetime .timedelta (weeks = 0 , days = 0 , hours = 1 , minutes = 0 , seconds = 0 , milliseconds = 0 )
114+ group_size = dt .timedelta (weeks = 0 , days = 0 , hours = 1 , minutes = 0 , seconds = 0 , milliseconds = 0 )
105115# Amount of info to show about each group:
106116# 0: None
107117# 1: Number of points in group
@@ -113,12 +123,12 @@ def dist_btw_two_points(p1,p2):
113123####################
114124
115125# Converter
116- ts2datetime = lambda x : datetime .datetime .utcfromtimestamp (int (x / 1e3 )).strftime ('%Y-%m-%d %H:%M:%S' )
126+ ts2datetime = lambda x : dt .datetime .utcfromtimestamp (int (x / 1e3 )).strftime ('%Y-%m-%d %H:%M:%S' )
117127
118128# Get time boundary index
119129# np.searchsorted is a fast way to find the first element that is larger than the threshold. 1 is for True
120- begin_index = np .searchsorted (timestampMs >= begin_ts , 1 )
121- end_index = np .searchsorted (timestampMs >= end_ts , 1 )
130+ begin_index = np .searchsorted (timestamp >= begin_ts , 1 )
131+ end_index = np .searchsorted (timestamp >= end_ts , 1 )
122132
123133# Get group_size in milliseconds
124134grpsMs = group_size .total_seconds ()* 1000
@@ -141,23 +151,23 @@ def dist_btw_two_points(p1,p2):
141151prev = 0 # Keeps in memory the last timestamp displayed
142152for i in range (close_points .size ):
143153 # If the delta between timestamps is bigger than the group size, or if it's the beginning or the end.
144- if timestampMs [close_points [i ]]- timestampMs [close_points [prev ]] > grpsMs or i == 0 or i == close_points .size - 1 :
154+ if timestamp [close_points [i ]]- timestamp [close_points [prev ]] > grpsMs or i == 0 or i == close_points .size - 1 :
145155 # If it's not the beginning and there are at least 2 points to make a group.
146156 if i > 0 and i - prev > 2 :
147157 if i == close_points .size - 1 : i = i + 1
148158 if group_verbosity == 1 :
149159 print ("\t Group of %d points" % (i - prev - 2 ))
150160 if group_verbosity == 2 :
151161 print ("\n \t Group of %d points: %d -> %d" % (i - prev - 2 ,close_points [prev + 1 ],close_points [i - 1 ]))
152- pt_date_im1 = ts2datetime (timestampMs [close_points [i - 1 ]])
153- pt_date_prevp1 = ts2datetime (timestampMs [close_points [prev + 1 ]])
162+ pt_date_im1 = ts2datetime (timestamp [close_points [i - 1 ]])
163+ pt_date_prevp1 = ts2datetime (timestamp [close_points [prev + 1 ]])
154164 print ("\t From: %s" % pt_date_prevp1 )
155165 print ("\t To : %s" % pt_date_im1 )
156166 print ("\t Mean dist to POI: %0.1fm\n " % np .mean (dist2poi [prev + 1 :i ]))
157167
158168 # if group_verbosity == 2: print() # Add space between lines
159169 # Else, display the point, unless it's the end
160170 if i != close_points .size :
161- pt_date = ts2datetime (timestampMs [close_points [i ]])
171+ pt_date = ts2datetime (timestamp [close_points [i ]])
162172 print ("Point %d -- Date: %s -- Distance to POI: %dm" % (close_points [i ],pt_date ,dist2poi [i ]))
163173 prev = i
0 commit comments