Pulsar EventTime: Transitioning from UTC Epochs to Timezone-Aware Timestamps
0 reputation · 05 Feb 2025, 16:53 UTC
0 reputation · 05 Feb 2025, 16:53 UTC
Apache Pulsar (version 2.11.x) utilizes a UTC epoch millisecond value for eventTime. While this ensures a consistent global timeline, it places the burden of regional time zone conversion and date interpretation entirely on the producer and consumer applications.
Currently, brokers do not interpret or store timezone metadata. To convey regional offsets, developers often implement custom message properties (e.g., eventTimeZone). However, because the broker ignores these properties for internal logic, there is no native mechanism to ensure consistency across diverse consumer implementations or to perform broker-side windowing based on local time.
This creates a gap in stream processing pipelines where event-time windowing must align with specific regional calendars rather than a strict UTC timeline.
35275 reputation · 06 Feb 2025, 01:42 UTC
Is there a documented path toward a native timezone‑aware timestamp type in Pulsar 2.11.x? No. The 2.11.x API exposes only a 64‑bit UTC epoch value for eventTime, and the broker’s internal data model contains no field for a timezone or offset. The official roadmap for 2.11.x and the 2.12.x release notes contain no mention of a future migration to a timezone‑aware type, and the source code for the 2.11.x branch confirms this absence.
Recommended approach for maintaining regional date integrity without ad‑hoc properties? Use an explicit contract in your application layer: encode the desired local time in the message payload (e.g., an ISO‑8601 string with offset) or, if you prefer to keep the timestamp separate, add a dedicated message property such as eventTimeZone. Then perform any timezone conversion in a Pulsar Function or in the consumer before applying windowing logic. This keeps the broker agnostic while guaranteeing consistent interpretation across all consumers.
eventTimeUtc (long) and eventTimeZone (string).producer.newMessage()
.eventTime(System.currentTimeMillis())
.property("eventTimeZone", "America/New_York")
.value(payload)
.send();
eventTimeUtc and eventTimeZone, converts the UTC epoch to a ZonedDateTime in the specified zone, and writes the result back as a new field (e.g., eventTimeLocal). The function can also emit the message to a “normalized” topic for downstream consumers.public class TimezoneNormalizer implements Function<Message<MySchema>, Message<MySchema>> {
@Override
public Message<MySchema> process(Message<MySchema> msg, Context ctx) {
long utcMillis = msg.getEventTimeUtc();
String zoneId = msg.getEventTimeZone();
ZonedDateTime local = Instant.ofEpochMilli(utcMillis)
.atZone(ZoneId.of(zoneId));
MySchema newPayload = new MySchema(utcMillis, zoneId, local.toEpochSecond());
return ctx.newMessage(newPayload);
}
}
eventTimeLocal field for windowing, aggregation, or any time‑based logic. Because the field is now a simple epoch value in the local zone, the consumer can safely apply standard windowing functions.eventTimeLocal matches the expected local epoch (e.g., 2026‑10‑19T17:16:44-04:00 for America/New_York).pulsar-client or a simple Java consumer to print the fields and confirm alignment.eventTimeZone property; it merely stores it as metadata.eventTimeLocal, windowing engines that rely on epoch values can operate without modification.Apache Pulsar does not expose a windowing API that understands local calendars. The only way to get broker‑side windowing that respects a specific zone is to pre‑convert the timestamp before the message reaches the broker (e.g., by publishing the local epoch instead of UTC). However, this sacrifices the ability to reconstruct the original UTC instant, so it is generally recommended to keep UTC and perform conversion downstream.
To tailor the function to your exact needs, could you confirm whether you have Pulsar Functions enabled in your cluster and whether you prefer to emit the local epoch to a separate topic or keep it within the same message payload?
| Step | What to Check |
|---|---|
| Schema Deployment | Producer and consumer both compile against the same schema. |
| Event Time Setting | Broker shows eventTime as UTC epoch. |
| Property Storage | Broker retains eventTimeZone property unchanged. |
| Function Output | Normalized topic contains eventTimeLocal matching expected local epoch. |
| Consumer Windowing | Aggregations based on eventTimeLocal produce correct results. |
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.