System timezone: America/Chicago (CDT, UTC-5), NTP-synced and confirmed correct
(timedatectl shows "System clock synchronized: yes", "NTP service: active")
Symptom
A downstream MeshCore observer aggregator (NebraskaMesh Analyzer) flags this
repeater with: "emitting zone-less local-time timestamps ... clock is
currently 5.0h behind UTC" and repeated clamp events. The offset (5.0h)
exactly matches this system's CDT UTC offset, despite the Pi's system clock
being correctly NTP-synchronized. This points to a timestamp-formatting bug
rather than an actual clock problem.
When it receives one of these naive strings, it relabels the value
as UTC without converting it, rather than treating it as local time and
calling .astimezone(timezone.utc).
Combined effect: a timestamp that is actually local wall-clock time
(e.g., CDT) is exported over MQTT/Glass with a "Z" (UTC) suffix, producing
a systematic offset equal to the host's local UTC offset. Any repeater
running outside UTC will trigger this on downstream observers.
Suggested fix
Ensure all datetime.now() / datetime.fromtimestamp() calls feeding
logs/telemetry pass tz=timezone.utc explicitly at creation, so values
are timezone-aware from the start.
In _to_rfc3339_timestamp(), if a naive datetime is received, either
reject/warn rather than silently stamping it UTC, or explicitly localize
it using the system's local tzinfo before converting to UTC.
Impact: Likely affects every deployment running outside UTC — probably
the majority of installs — causing false clock-skew/clamp warnings and
corrupting propagation-delay analytics on any observer platform that
trusts the "Z" suffix.
I found this via the NebraskaMesh Analyzer's clamp-detection banner.
**Environment**
- openhop_repeater v1.1.2.dev1, core v1.1.1
- Raspberry Pi 5, Debian 12 (Bookworm)
- System timezone: America/Chicago (CDT, UTC-5), NTP-synced and confirmed correct
(`timedatectl` shows "System clock synchronized: yes", "NTP service: active")
**Symptom**
A downstream MeshCore observer aggregator (NebraskaMesh Analyzer) flags this
repeater with: "emitting zone-less local-time timestamps ... clock is
currently 5.0h behind UTC" and repeated clamp events. The offset (5.0h)
exactly matches this system's CDT UTC offset, despite the Pi's system clock
being correctly NTP-synchronized. This points to a timestamp-formatting bug
rather than an actual clock problem.
**Root cause**
1. `repeater/web/http_server.py` line 86:
```python
"timestamp": datetime.fromtimestamp(record.created).isoformat(),
```
Called without a `tz` argument, `datetime.fromtimestamp()` converts the
epoch value to a **naive local-time** datetime (no tzinfo attached)
instead of UTC.
2. `repeater/data_acquisition/glass_handler.py`, `_to_rfc3339_timestamp()`
(~lines 1146-1166):
```python
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
```
When it receives one of these naive strings, it **relabels** the value
as UTC without converting it, rather than treating it as local time and
calling `.astimezone(timezone.utc)`.
**Combined effect:** a timestamp that is actually local wall-clock time
(e.g., CDT) is exported over MQTT/Glass with a "Z" (UTC) suffix, producing
a systematic offset equal to the host's local UTC offset. Any repeater
running outside UTC will trigger this on downstream observers.
**Suggested fix**
- Ensure all `datetime.now()` / `datetime.fromtimestamp()` calls feeding
logs/telemetry pass `tz=timezone.utc` explicitly at creation, so values
are timezone-aware from the start.
- In `_to_rfc3339_timestamp()`, if a naive datetime is received, either
reject/warn rather than silently stamping it UTC, or explicitly localize
it using the system's local tzinfo before converting to UTC.
**Impact:** Likely affects every deployment running outside UTC — probably
the majority of installs — causing false clock-skew/clamp warnings and
corrupting propagation-delay analytics on any observer platform that
trusts the "Z" suffix.
I found this via the NebraskaMesh Analyzer's clamp-detection banner.
<!-- github-sync-id:4821606544 -->
just waiting to be tested and merged into dev/main
this has been worked on / fixed and reported here - https://github.com/openhop-dev/openhop_repeater/issues/305
and the PR https://github.com/openhop-dev/openhop_repeater/pull/333
just waiting to be tested and merged into dev/main
<!-- github-comment-id:4895981999 -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Environment
(
timedatectlshows "System clock synchronized: yes", "NTP service: active")Symptom
A downstream MeshCore observer aggregator (NebraskaMesh Analyzer) flags this
repeater with: "emitting zone-less local-time timestamps ... clock is
currently 5.0h behind UTC" and repeated clamp events. The offset (5.0h)
exactly matches this system's CDT UTC offset, despite the Pi's system clock
being correctly NTP-synchronized. This points to a timestamp-formatting bug
rather than an actual clock problem.
Root cause
repeater/web/http_server.pyline 86:Called without a
tzargument,datetime.fromtimestamp()converts theepoch value to a naive local-time datetime (no tzinfo attached)
instead of UTC.
repeater/data_acquisition/glass_handler.py,_to_rfc3339_timestamp()(~lines 1146-1166):
When it receives one of these naive strings, it relabels the value
as UTC without converting it, rather than treating it as local time and
calling
.astimezone(timezone.utc).Combined effect: a timestamp that is actually local wall-clock time
(e.g., CDT) is exported over MQTT/Glass with a "Z" (UTC) suffix, producing
a systematic offset equal to the host's local UTC offset. Any repeater
running outside UTC will trigger this on downstream observers.
Suggested fix
datetime.now()/datetime.fromtimestamp()calls feedinglogs/telemetry pass
tz=timezone.utcexplicitly at creation, so valuesare timezone-aware from the start.
_to_rfc3339_timestamp(), if a naive datetime is received, eitherreject/warn rather than silently stamping it UTC, or explicitly localize
it using the system's local tzinfo before converting to UTC.
Impact: Likely affects every deployment running outside UTC — probably
the majority of installs — causing false clock-skew/clamp warnings and
corrupting propagation-delay analytics on any observer platform that
trusts the "Z" suffix.
I found this via the NebraskaMesh Analyzer's clamp-detection banner.
this has been worked on / fixed and reported here - https://github.com/openhop-dev/openhop_repeater/issues/305
and the PR https://github.com/openhop-dev/openhop_repeater/pull/333
just waiting to be tested and merged into dev/main
Great news! Thank you.