Tutorial: Die fünf Zeitstempelformate eines Tracking-Stapels und ihre Umrechnung

Management Summary
Zeitstempel geben Analysesystemen an, wann ein Kauf oder anderer Vorgang stattgefunden hat. Unterschiedliche Werkzeuge verwenden verschiedene Einheiten und Zeitzonen; Verwechslungen können dasselbe Ereignis dem falschen Berichtstag zuordnen. UTC als gemeinsame weltweite Zeitbasis erleichtert Vergleiche. Ereigniszeit und Zeitpunkt des Datenempfangs bleiben dennoch verschiedene Angaben. Einheitliche Zeitverarbeitung hilft deshalb beim Abgleich von Verkaufsberichten, besonders rund um Mitternacht und Zeitumstellungen.
Inhalt
- 1. Fünf häufige Darstellungen unterscheiden
- 2. Mit ausdrücklich angegebener Einheit umrechnen
- 3. GA4-Berichtstag und Zeitstempel getrennt betrachten
- 4. BigQuery-Funktionen passend zur Einheit verwenden
- 5. Sommerzeit erzeugt doppelte und fehlende Uhrzeiten
- 6. Die Vorgaben der empfangenden Schnittstelle beachten
- Fragen und Antworten
- Quellen und technische Dokumentation
Ein Tracking-Ereignis kann als Unix-Sekunden, Millisekunden, Mikrosekunden oder Text mit UTC-Versatz vorliegen. Der Versatz beschreibt den Abstand zu UTC: +02:00 bedeutet zwei Stunden voraus. Bei 12:00 UTC zeigt eine Uhr mit dem Versatz +02:00 bereits 14:00. Zusätzlich speichern Berichte ein Kalenderdatum. Eine zuverlässige Umrechnung braucht drei Angaben: die Einheit, die Bedeutung des Feldes und die gewünschte Zeitzone.
Browserzeit, Containerstart, Ereigniszeit und Empfangszeit sind nicht automatisch derselbe Augenblick. Erst nach diesem Bedeutungsabgleich ist ein Vergleich der Zahlen sinnvoll. Die Stellenzahl liefert einen Hinweis, ersetzt aber keine Felddefinition.

1. Fünf häufige Darstellungen unterscheiden
Die folgenden Beispiele beziehen sich auf 2026-09-26T23:30:00Z, in Berlin also auf den 27. September 2026 um 01:30 Uhr. Nur die ersten drei Formate zählen Einheiten seit der Unix-Epoche am 1. Januar 1970 um 00:00 UTC. Eine ISO-Darstellung schreibt Kalenderfelder; ein Datum allein bezeichnet überhaupt keinen einzelnen Zeitpunkt.
| Darstellung | Beispiel | Bedeutung |
|---|---|---|
| Sekunden | 1790465400 | Unix-Sekunden, etwa Meta event_time |
| Millisekunden | 1790465400000 | Unix-Millisekunden, etwa Date.now() |
| Mikrosekunden | 1790465400000000 | Unix-Mikrosekunden, etwa GA4 event_timestamp |
| ISO 8601 / RFC 3339 | 2026-09-27T01:30:00+02:00 | Kalenderfelder mit ausdrücklichem Versatz |
| Kalenderdatum | 20260927 | Berliner Datum im Beispiel, kein Zeitpunkt |
Date.now() liefert Millisekunden der aktuellen Systemuhr. gtm.start im üblichen GTM-Einbau bezeichnet den Start des Containers, nicht den Zeitpunkt jedes späteren Klicks. Die Einheit kann korrekt sein, während die fachliche Zuordnung trotzdem falsch ist.
Bei Zeitwerten aus dem Jahr 2026 sind zehn, 13 und 16 Ziffern typisch für Sekunden, Millisekunden und Mikrosekunden. Alte oder negative Zeitwerte, andere Epochen und gewöhnliche Kennnummern passen nicht in diese Erkennung. Auch acht Ziffern beweisen kein gültiges Datum: 20260230 ist kein Kalendertag.
2. Mit ausdrücklich angegebener Einheit umrechnen
Die Funktion akzeptiert ganze Zahlen oder Zeichenketten aus Dezimalziffern mit optionalem Vorzeichen. Einheit und Wert werden getrennt übergeben. Gleitkommazahlen, Boolesche Werte und Zeichenketten mit Nachkommastellen werden abgewiesen, damit keine unbemerkte Rundung entsteht. Nanosekunden sind nur zulässig, wenn eine exakte Abbildung auf Mikrosekunden möglich ist.
import re
from datetime import datetime, timedelta, timezone
EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
def epoch_to_utc(value, unit):
if isinstance(value, bool):
raise TypeError("boolean is not a timestamp")
if isinstance(value, str):
if not re.fullmatch(r"[+-]?[0-9]{1,20}", value):
raise ValueError("expected an integer string")
value = int(value)
elif not isinstance(value, int):
raise TypeError("expected an integer or integer string")
factors = {"s": 1_000_000, "ms": 1_000, "us": 1}
if unit == "ns":
micros, remainder = divmod(value, 1_000)
if remainder:
raise ValueError("nanoseconds would lose precision")
elif unit in factors:
micros = value * factors[unit]
else:
raise ValueError("unit must be s, ms, us or ns")
try:
return EPOCH + timedelta(microseconds=micros)
except OverflowError as exc:
raise ValueError("outside Python datetime range") from exc
print(epoch_to_utc("1790465400000000", "us").isoformat())
# 2026-09-26T23:30:00+00:00Das Ergebnis ist eine UTC-datetime mit Mikrosekundenauflösung. Die Funktion prüft Typ, Einheit und den darstellbaren Python-Bereich, aber keine fachlichen Uploadfristen. Ob ein Datum zum Ereignis passt, braucht eine zusätzliche Plausibilitätsprüfung anhand der Quelle. Eine falsch deklarierte Einheit kann weiterhin ein technisch gültiges, fachlich falsches Datum ergeben.
Beispielsweise ergeben 1790465400 als Millisekunden den 1970-01-21T17:21:05.400Z. Millisekunden irrtümlich als Sekunden können einen sehr fernen Zeitpunkt oder einen Bereichsfehler erzeugen. Auch ein offensichtlich falsches Datum ist nicht harmlos, sobald eine Schnittstelle oder ein Bericht den Wert weiterverarbeitet.
3. GA4-Berichtstag und Zeitstempel getrennt betrachten
Das aktuelle GA4-Exportschema beschreibt event_timestamp als Empfangszeit bei Google Analytics in Mikrosekunden UTC. Mehrere Ereignisse derselben Anfrage können denselben Zeitstempel tragen. Der Wert ist deshalb weder ein eindeutiger Ereignisschlüssel noch ohne weitere Prüfung eine genaue Klickzeit.
event_date ist das erfasste Datum im Format YYYYMMDD nach der hinterlegten Berichtszeitzone. Die täglichen Tabellen heißen events_YYYYMMDD. Ein aus dem Empfangszeitstempel berechneter lokaler Tag und das gespeicherte Ereignisdatum dürfen nicht pauschal gleichgesetzt werden: Verzögerungen, Bedeutung des jeweiligen Zeitfelds und Änderungen der Berichtszeitzone benötigen eine eigene Prüfung.
Für den reinen Zeitzonenvergleich desselben Beispielzeitpunkts gilt:
UTC 2026-09-26T23:30:00Z
Europe/Berlin 2026-09-27T01:30:00+02:00
UTC-Datum 2026-09-26
Berliner Datum 2026-09-27Berlin liegt im September zwei Stunden vor UTC, im Winter normalerweise eine Stunde. Ein lokaler Tagesbericht und ein UTC-Tagesbericht schneiden deshalb unterschiedliche Zeiträume aus. Die Differenz der Tagessummen ist nicht konstant: Am Anfang und Ende verschieben sich Ereignisse, deren Anzahl vom tatsächlichen Verkehr abhängt.
Für Vergleiche müssen Tagesdefinition, Ereignisbegriff, Filter und Datenstand zusammenpassen. Ein Tabellenfilter wählt Exporttabellen; ein zusätzlicher Zeitstempelfilter wählt Zeitpunkte innerhalb dieser Tabellen. Soll ein anderer Berichtstag rekonstruiert werden, müssen auch mögliche Randtabellen und verspätete Daten berücksichtigt werden. Ein LIMIT begrenzt lediglich die Ausgabe, nicht zuverlässig die gelesenen Bytes.
4. BigQuery-Funktionen passend zur Einheit verwenden
TIMESTAMP_SECONDS, TIMESTAMP_MILLIS und TIMESTAMP_MICROS erwarten die jeweils benannte Einheit. Dieses Beispiel liest nur einige Felder einer ausdrücklich benannten Tagestabelle. Projekt, Dataset, Datum und Berichtszeitzone sind anzupassen.
SELECT
event_date,
event_timestamp,
TIMESTAMP_MICROS(event_timestamp) AS timestamp_utc,
DATETIME(TIMESTAMP_MICROS(event_timestamp),
'Europe/Berlin') AS wall_clock_berlin,
DATE(TIMESTAMP_MICROS(event_timestamp)) AS date_utc,
DATE(TIMESTAMP_MICROS(event_timestamp),
'Europe/Berlin') AS timestamp_date_berlin,
FORMAT_TIMESTAMP('%Y-%m-%dT%H:%M:%E6S%Ez',
TIMESTAMP_MICROS(event_timestamp),
'Europe/Berlin') AS text_with_offset,
UNIX_SECONDS(TIMESTAMP_MICROS(event_timestamp)) AS whole_seconds
FROM `project_id.analytics_123456789.events_20260927`
LIMIT 10;TIMESTAMP bezeichnet einen Zeitpunkt. DATETIME enthält Kalenderdatum und Uhrzeit ohne Zeitzone. Die lokale Darstellung ist nützlich, aber ohne zusätzliche Angaben nicht eindeutig zurückrechenbar. %E6S erhält sechs Nachkommastellen in der Textausgabe; UNIX_SECONDS rundet dagegen auf den Beginn der betreffenden Sekunde ab und verliert den Mikrosekundenanteil.
Beim Einlesen eines Texts unterscheiden sich ein ausdrücklicher Versatz, eine ausdrücklich angegebene Zone und der UTC-Standard:
SELECT
PARSE_TIMESTAMP('%FT%T%Ez', '2026-09-27T01:30:00+02:00') AS explicit_offset,
PARSE_TIMESTAMP('%FT%T', '2026-09-27T01:30:00',
'Europe/Berlin') AS explicit_zone,
PARSE_TIMESTAMP('%FT%T', '2026-09-27T01:30:00') AS utc_default;Die ersten beiden Ergebnisse bezeichnen hier 2026-09-26T23:30:00Z, das dritte 2026-09-27T01:30:00Z. Das sind zwei Stunden Unterschied. Eine Formatzeichenkette allein garantiert keine richtige Zeitzone; auch andere unterstützte Parsingfunktionen benötigen klare Regeln für Einheit, Format und Zeitzone der Eingabe.
5. Sommerzeit erzeugt doppelte und fehlende Uhrzeiten
In Europe/Berlin kommt am 25. Oktober 2026 die lokale Uhrzeit 02:30 zweimal vor: mit +02:00 entspricht die Angabe 00:30 UTC, mit +01:00 dagegen 01:30 UTC. Der Zonenname allein löst diese Mehrdeutigkeit nicht. Ein bekannter Versatz oder eine ausdrücklich gespeicherte Auswahl des ersten beziehungsweise zweiten Durchlaufs ist erforderlich.
Am 29. März 2026 existiert 02:30 Berliner Ortszeit dagegen nicht, weil die Uhr von 02:00 auf 03:00 springt. Ein Parser kann solche Eingaben verschieben, ablehnen oder nach einer eigenen Regel behandeln. Eine stillschweigende Vorgabe ist keine Rekonstruktion des tatsächlichen Ereignisses.
Diese beiden Kalendertage dauern 25 beziehungsweise 23 Stunden. Tagesgrenzen werden deshalb aus lokaler Mitternacht und der nächsten lokalen Mitternacht berechnet, anschließend in UTC umgewandelt. Einfach 86.400 Sekunden zu addieren ist dafür keine allgemeine Regel.
Für bereits eingetretene Ereignisse ist ein eindeutig bestimmter UTC-Zeitpunkt zweckmäßig. Die ursprüngliche Zeitzone und der Quelltext können zusätzlich zur Nachvollziehbarkeit erhalten bleiben. UTC-Speicherung repariert jedoch keine zuvor falsch interpretierte Ortszeit.
6. Die Vorgaben der empfangenden Schnittstelle beachten
Meta CAPI verwendet für event_time Unix-Sekunden des tatsächlichen Ereignisses. Date.now() darf daher nicht unverändert als dieser Wert gesendet werden. Zulässiges Ereignisalter und Fehlerbehandlung gehören zur konkreten Schnittstelle und Ereignisquelle; eine erfolgreiche HTTP-Antwort ist allein kein Nachweis vollständiger Verarbeitung oder Attribution. Fehlerobjekte, Rückmeldungen und Diagnosen sind zusätzlich auszuwerten.
Für ClickConversion.conversion_date_time der Google Ads API verlangt die Dokumentation eine Zeitzonenangabe im Format yyyy-mm-dd hh:mm:ss+|-hh:mm. Das passende Beispiel lautet 2026-09-27 01:30:00+02:00. Ein fehlender Versatz darf nicht pauschal als Rückfall auf die Kontozeitzone verstanden werden. Andere Uploadwege haben eigene Vorgaben.
Bei Wiederholungen bleibt die tatsächliche Ereigniszeit maßgeblich. Ein altes Ereignis durch „jetzt“ zu ersetzen, um eine Frist zu umgehen, verfälscht die Daten. Nach einer belegten Uhrkorrektur müssen ursprüngliche Ereigniszeit, zulässiges Fenster und Duplikatschutz gemeinsam geprüft werden.
Fragen und Antworten
Sind 16-stellige Mikrosekunden in JavaScript immer exakt?
Nein. Number.MAX_SAFE_INTEGER beträgt 9007199254740991. Der Beispielwert aus 2026 liegt darunter, aber nicht jede 16-stellige Zahl. Die Grenze entspricht bei Mikrosekunden dem 5. Juni 2255 um 23:47:34.740991 UTC. Date arbeitet dennoch mit Millisekunden; eine sichere ganze Mikrosekundenzahl lässt sich nicht unverändert als Date-Wert verwenden.
Was gilt für Nanosekunden und JSON?
Heutige Unix-Nanosekunden überschreiten die sichere Ganzzahlgrenze von JavaScript. Manche Werte bleiben zufällig darstellbar, benachbarte Werte jedoch nicht. Eine Dezimalzeichenkette und anschließendes BigInt erhalten die Zahl. Eine bereits beim Einlesen als Number gerundete Zahl wird durch spätere BigInt-Umwandlung nicht repariert. Die Verringerung auf Millisekunden verliert bewusst Genauigkeit.
Löst UTC als Property-Zeitzone alle Tagesunterschiede?
UTC vereinheitlicht die gewählte Tagesgrenze, aber nicht unterschiedliche Bedeutungen der Zeitfelder, Verarbeitung oder Attribution. Für einen Berliner Geschäftstag kann eine lokale Zeitzone weiterhin passend sein. Eine Änderung der Property-Zeitzone wirkt nur für zukünftige Daten und kann Übergangseffekte in Berichten erzeugen; die Historie wird nicht vollständig neu berechnet.
Wie lässt sich eine abweichende Serveruhr untersuchen?
timedatectl status zeigt auf passenden Linux-Systemen den Synchronisationsstatus. Ein fehlender Abgleich beweist noch keine konkrete Abweichung. Beim verwendeten Zeitdienst sind zusätzlich Offset, letzte erfolgreiche Synchronisation und Erreichbarkeit der Zeitquelle relevant. Ein HTTP-Date-Header ist nur eine grobe Gegenprobe: Cache, Übertragungsdauer, Sekundengenauigkeit und die antwortende Infrastruktur begrenzen die Aussage. Eine garantierte Genauigkeit von einer Sekunde folgt daraus nicht.


