Strip pre-2000 leading points to prevent epoch-zero start time and absurd duration

This commit is contained in:
Davide Scaini
2026-05-12 23:11:33 +02:00
parent 867da767eb
commit 0b266d208c
4 changed files with 25 additions and 4 deletions
+19 -1
View File
@@ -5,9 +5,27 @@ It gets fed into metrics computation and the BAS JSON writer.
""" """
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime from datetime import datetime, timezone
from typing import Optional from typing import Optional
# Any timestamp before this is almost certainly an uninitialised sensor value
# (epoch 0, FIT "no-data" sentinel, RTC not yet synced, etc.).
_MIN_TIMESTAMP = datetime(2000, 1, 1, tzinfo=timezone.utc)
def strip_bogus_leading_points(points: list["DataPoint"]) -> list["DataPoint"]:
"""Drop leading points whose timestamp predates the year 2000.
FIT files occasionally emit a record with timestamp=0 (or another
pre-2000 value) as an uninitialised sentinel before the real data
begins. Keeping such a point as points[0] produces a 1970 start
time and an absurdly large duration_s.
"""
i = 0
while i < len(points) and points[i].timestamp < _MIN_TIMESTAMP:
i += 1
return points[i:]
@dataclass @dataclass
class DataPoint: class DataPoint:
+2 -1
View File
@@ -6,7 +6,7 @@ from typing import Any
import fitdecode import fitdecode
from bincio.extract.models import DataPoint, LapData, ParsedActivity from bincio.extract.models import DataPoint, LapData, ParsedActivity, strip_bogus_leading_points
from bincio.extract.sport import normalise_sport from bincio.extract.sport import normalise_sport
@@ -101,6 +101,7 @@ class FitParser:
) )
) )
points = strip_bogus_leading_points(points)
if not points: if not points:
raise ValueError(f"No record messages found in {path.name}") raise ValueError(f"No record messages found in {path.name}")
+2 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import gpxpy import gpxpy
import gpxpy.gpx import gpxpy.gpx
from bincio.extract.models import DataPoint, ParsedActivity from bincio.extract.models import DataPoint, ParsedActivity, strip_bogus_leading_points
from bincio.extract.parsers.base import BaseParser from bincio.extract.parsers.base import BaseParser
from bincio.extract.sport import normalise_sport, normalise_sub_sport from bincio.extract.sport import normalise_sport, normalise_sub_sport
@@ -38,6 +38,7 @@ class GpxParser(BaseParser):
_apply_extensions(pt, dp) _apply_extensions(pt, dp)
points.append(dp) points.append(dp)
points = strip_bogus_leading_points(points)
if not points: if not points:
raise ValueError(f"No trackpoints found in {path.name}") raise ValueError(f"No trackpoints found in {path.name}")
+2 -1
View File
@@ -5,7 +5,7 @@ from pathlib import Path
from lxml import etree from lxml import etree
from bincio.extract.models import DataPoint, ParsedActivity from bincio.extract.models import DataPoint, ParsedActivity, strip_bogus_leading_points
from bincio.extract.sport import normalise_sport, normalise_sub_sport from bincio.extract.sport import normalise_sport, normalise_sub_sport
_NS_HTTP = { _NS_HTTP = {
@@ -73,6 +73,7 @@ class TcxParser:
) )
points.append(dp) points.append(dp)
points = strip_bogus_leading_points(points)
if not points: if not points:
raise ValueError(f"No trackpoints found in {path.name}") raise ValueError(f"No trackpoints found in {path.name}")