Latest Avro compiler (1.8.2) generates java sources for dates logical types with Joda-Time based implementations. How can I configure Avro compiler to produce sources that used Java 8 date-time API?
6 Answers
Currently (avro 1.8.2) this is not possible. It's hardcoded to generate Joda date/time classes.
The current master
branch has switched to Java 8 and there is an open issue (with Pull Request) to add the ability to generate classes with java.time.*
types.
I have no idea on any kind of release schedule for whatever is currently in master
unfortunately. If you feel adventurous you can apply the patch to 1.8.2
, since in theory it should all be compatible. The underlying base types when serializing / deserializing are still integers and longs.

- 534
- 5
- 16
You need to create your own Conversions to support java-8 date-time api, below is a conversion for java.time.LocalDate
:
class Java8LocalDateConversion extends Conversion<LocalDate> {
@Override
public Class<LocalDate> getConvertedType() {
return LocalDate.class;
}
@Override
public String getLogicalTypeName() {
// v--- reuse the logical type `date`
return "date";
}
@Override
// convert LocalDate to Integer
public Integer toInt(LocalDate value, Schema schema, LogicalType type) {
return (int) value.toEpochDay();
}
@Override
// parse LocalDate from Integer
public LocalDate fromInt(Integer value, Schema schema, LogicalType type) {
return LocalDate.ofEpochDay(value);
}
}
The logical types can be reused in avro, so you can using the existing date
logical type, for example:
Schema schema = LogicalTypes.date().addToSchema(Schema.create(Type.INT));
For the serializing & deserializing you should set the GenericData
which will find your own conversion, for example:
//serializing
DatumWriter<T> out = new SpecificDatumWriter<>(schema, data());
// deserializing
DatumReader<T> in = new SpecificDatumReader<>(schema, schema, data());
private SpecificData data() {
SpecificData it = new SpecificData();
it.addLogicalTypeConversion(new Java8LocalDateConversion());
return it;
}
If you don't want to configure the GenericData
every time, you can use the global GenericData
instead, for example:
// register the conversion globally ---v
SpecificData.get().addLogicalTypeConversion(new Java8LocalDateConversion());

- 29,655
- 7
- 72
- 83
-
1here is the test I wrote on [github](https://github.com/holi-java/api-tests/blob/6d09966f007bd6ea6089a5f638275ae0ff5b2a67/avro/src/test/java/test/avro/AvroTypesTest.java#L51_L55). – holi-java Aug 16 '17 at 15:16
-
1It doesn't solve a problem: avro compiler still generate joda's date field for such logical type. – injecto Aug 17 '17 at 07:41
- use Avro version >=
1.9.0
<1.10.0
- add
<dateTimeLogicalTypeImplementation>jsr310</dateTimeLogicalTypeImplementation>
intoconfiguration
section. - use Avro version >=
1.10.0
- java8/jsr310 native date/time classes used by default

- 476
- 3
- 12
With avro 1.9.2 you can use e.g. date for LocalDate
:
{
"name": "Transaction",
"type": "record",
"fields": [
{
"name": "time",
"type": {
"type": "int",
"logicalType": "date"
}
},
See Logical Types for the other types.

- 3,321
- 2
- 29
- 46
Avro v1.11.0 TimeConversions has built-in support for Java 8 time classes such as LocalDate
, Instant
, etc. The TimeConversions
must be registered with the SpecificData
class or its sub-classes, such as ReflectData
. Here is a complete example of how to use TimeConversions
:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account
{
private int id;
private LocalDate createdOn;
public static void main(String[] args) throws IOException
{
// create schema from POJO Account class
ReflectData reflectData = ReflectData.get();
reflectData.addLogicalTypeConversion(new TimeConversions.DateConversion());
Schema schema = reflectData.getSchema(Account.class);
System.out.println("Schema in JSON:\n" + schema + "\n");
// create avro writer
DatumWriter<Account> datumWriter = new ReflectDatumWriter<>(schema);
DataFileWriter<Account> dataFileWriter = new DataFileWriter<>(datumWriter);
// dataFileWriter.setCodec(CodecFactory.snappyCodec()); // for compression
dataFileWriter.create(schema, new File("accounts.avro"));
dataFileWriter.append(new Account(123, LocalDate.of(2001, 1, 1)));
dataFileWriter.append(new Account(234, LocalDate.of(2002, 2, 2)));
dataFileWriter.close();
// create avro reader
DatumReader<Account> datumReader = new ReflectDatumReader<>(schema);
DataFileReader<Account> dataFileReader = new DataFileReader<>(new File("accounts.avro"), datumReader);
dataFileReader.forEach(System.out::println);
}
}

- 471
- 3
- 9
AVRO 1.10 added support for LocalDateTime
, see Apache Avro™ 1.10.0 Specification

- 190
- 11
-
There is no such thing as "LocalDateTime" on the page you referenced. – Donald Duck Feb 18 '21 at 18:25
-
I meant "Local timestamp". This gets translated into "LocalDateTime" in Java. – fml2 Feb 19 '21 at 14:17