Kafka AVRO
Data Conversion
Long to Datetime
Data Processing
Programming

Kafka AVRO - conversion from long to datetime

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Kafka and Avro pipelines, timestamps are often stored as long values representing epoch milliseconds. Converting that value to a datetime is easy in application code, but the better long-term fix is usually to model the field as an Avro logical timestamp instead of leaving it as an anonymous number.

What the Long Value Usually Means

A raw Avro long is just a 64-bit integer. By convention, teams often use it for one of these timestamp encodings:

  • epoch milliseconds
  • epoch microseconds
  • epoch seconds

You must know which unit the producer wrote. A value in milliseconds interpreted as seconds produces a completely wrong date, often off by decades.

For example, 1704067200000 is 2024-01-01T00:00:00Z in milliseconds, not seconds.

Prefer Avro Logical Types

Avro can describe time semantics directly in the schema. Instead of a plain long, define the field with a logical type such as timestamp-millis.

json
1{
2  "type": "record",
3  "name": "OrderEvent",
4  "fields": [
5    {
6      "name": "createdAt",
7      "type": {
8        "type": "long",
9        "logicalType": "timestamp-millis"
10      }
11    }
12  ]
13}

This does not change the underlying binary storage, but it tells readers and tooling what the number means.

Convert in Java

If the consumer receives a raw long, convert it explicitly with Instant and then apply a timezone when needed.

java
1import java.time.Instant;
2import java.time.ZoneId;
3import java.time.ZonedDateTime;
4
5public class TimestampConversion {
6    public static void main(String[] args) {
7        long epochMillis = 1704067200000L;
8
9        Instant instant = Instant.ofEpochMilli(epochMillis);
10        ZonedDateTime utc = instant.atZone(ZoneId.of("UTC"));
11        ZonedDateTime toronto = instant.atZone(ZoneId.of("America/Toronto"));
12
13        System.out.println(utc);
14        System.out.println(toronto);
15    }
16}

Use Instant for storage and transport semantics. Convert to ZonedDateTime or OffsetDateTime only when you need presentation in a specific timezone.

What Happens With Generic Records

When you use Avro GenericRecord, the field often still appears as a Long unless your serializer stack or code generation layer maps logical types into richer Java types for you. So code like this is common:

java
long createdAt = (Long) record.get("createdAt");
Instant instant = Instant.ofEpochMilli(createdAt);

That is normal. Logical type metadata helps schema readers and some tooling, but it does not guarantee your runtime object is already a datetime instance.

Timezone and Formatting Are Separate Decisions

A timestamp stored as epoch milliseconds is timezone-neutral. It represents a moment in UTC. The timezone question appears only when you render or interpret that moment for people.

So the usual safe flow is:

  1. read the long
  2. convert it to Instant
  3. keep it as Instant internally
  4. format it in a user-facing timezone only at the boundary

That prevents bugs where the same event appears to “change time” because one service interpreted the raw number as local time.

Common Pitfalls

The biggest mistake is confusing milliseconds and seconds. That single unit error causes dates that are obviously wrong once you inspect them, but it can still slip through tests if nobody checks real values.

Another mistake is storing a plain long without documenting the unit. If the schema does not use logicalType, future consumers have to guess.

A third mistake is converting immediately to local time and then passing the local representation through the rest of the system. Keep UTC-style instants internally.

Summary

  • A Kafka Avro timestamp stored as long is usually epoch milliseconds, but you must confirm the unit.
  • Use Avro timestamp-millis or a related logical type in the schema whenever possible.
  • In Java, convert with Instant.ofEpochMilli(...) and apply a timezone only for presentation.
  • Generic Avro records often still expose the field as Long, even with logical type metadata.
  • Treat timezone formatting as a display concern, not as part of the stored timestamp value.

Course illustration
Course illustration

All Rights Reserved.