Gestion du temps

Un fichier GPX contient, en plus de relevés GPS, des temps sous la forme d'une date et d'une heure nous permettant, par exemple, d'effectuer des calculs de vitesse. Dans ce nouveau chapitre, nous allons étudier quelques fonctions Python afin de manipuler les dates et les durées.

Le format ISO 8601

Le format GPX utilise le format ISO 8601 pour représenter une date. Une date est codée de la façon suivante :

YYYY-MM-DDThh:mm:ssZ

Code Signification
Y année sur 4 chiffres
M mois sur 2 chiffres
D jour sur 2 chiffres
h heure sur 2 chiffres
m minutes sur 2 chiffres
s secondes sur 2 chiffres (parfois complétées par 3 décimales pour une précision de l'ordre de la milliseconde)

La lettre Z correspond à la zone horaire selon l'échelle de temps UTC (Coordinated Universal Time). Elle peut-être suivie d'un décalage horaire.

Le format Unix Time Stamp

C'est une mesure du temps basée sur le nombre de secondes écoulées depuis le 1er janvier 1970 à 00h00m00s (époque Unix). Ce format numérique, contrairement au format ISO 8601 exprimé en texte, est particulièrement adapté à des calculs de durées.

Le module datetime

Comme le module math, ce module est préinstallé avec Python, donc pas besoin d'opération particulière pour l'utiliser. Il permet, entre autres, d'effectuer la conversion d'une date au format ISO 8601 en Unix Time Stamp.

from datetime import datetime as dt

birthday = '1972-08-31T08:51:42'
timestamp = dt.fromisoformat(birthday).timestamp()
print(birthday, ':', int(timestamp), 'secondes écoulées depuis l\'époque Unix')
1972-08-31T08:51:42 : 84095502 secondes écoulées depuis l'époque Unix

Exercice

Complétez le script gpxplorer.py en ajoutant une colonne timestamp au DataFrame contenant le Unix Time Stamp de chaque relevé GPS. Le script affichera, en plus de la distance parcourue, la date et l'heure du départ, la durée du parcours et enfin la vitesse moyenne.

Heure de départ : 2012-10-21T07:01:39
Durée : 8178.0 s
Distance parcourue : 21602 m
Vitesse moyenne : 9.51 km/h
Correction
from bs4 import BeautifulSoup as bs
import pandas as pd
from datetime import datetime as dt
from geopy import distance as dst

df = pd.DataFrame([], columns = [ 'datetime', 'timestamp', 'latitude', 'longitude', 'elevation', 'distance' ])

# Chargement du fichier GPX
content = open('data/RATJ2012-21km-herve.schely.gpx')

# Construction de l'arborescnce
root = bs(content, features='xml')

# Remplissage du DataFrame
k = 0
for point in root.find_all('trkpt'):
    df.loc[k, 'datetime'] = point.find('time').string[:19]
    df.loc[k, 'timestamp'] = round(dt.fromisoformat(df.loc[k, 'datetime']).timestamp())
    df.loc[k, 'latitude'] = float(point['lat'])
    df.loc[k, 'longitude'] = float(point['lon'])
    df.loc[k, 'elevation'] = float(point.find('ele').string)
    k = k + 1

# Calcul des distances cumulées
df.loc[0, 'distance'] = 0
for k in df.index[1:]:
    p1 = (df['latitude'][k-1], df['longitude'][k-1])
    p2 = (df['latitude'][k], df['longitude'][k])
    df.loc[k, 'distance'] = df.loc[k-1, 'distance']  + dst.geodesic(p1, p2).m

total_time = df['timestamp'].iloc[-1] - df['timestamp'][0]
total_distance = round(df['distance'].iloc[-1])

print('Heure de départ :', df['datetime'][0])
print('Durée :', total_time, 's')
print('Distance parcourue :', total_distance, 'm')
print('Vitesse moyenne :', round(total_distance / total_time * 3.6, 2), 'km/h')

Maintenant que nous avons extrait toutes les informations contenues dans un fichier GPX, nous pouvons les enregistrer dans un autre format (CSV par exemple) pour les traiter avec un autre logiciel ou les représenter sur une carte interactive : c'est justement ce qui va nous occuper dans le chapitre suivant.