在java上使用Avro发送和接收日期类型

时间:2018-03-02 19:34:20

标签: java apache-kafka avro

我可以通过Apache Avro发送和接收日期类型。我一直没能找到任何东西。只有我发现的东西说在模式中使用了Date和logicalType of Date。但这导致接收器端的另一个int。我仍然需要将它转换为日期。

我正在尝试从Apache Kafka制片人发送日期并在Kafka消费者中接收。

如果没有其他方式,那么我必须始终将日期转换为int,然后再转发给消费者。这篇文章介绍了如何做到这一点:

Get the number of days, weeks, and months, since Epoch in Java

串行器代码: -

@Override
    public byte[] serialize(String topic, T data) {
        try {
            byte[] result = null;

            if (data != null) {
                logger.debug("data='{}'" +  data);

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                BinaryEncoder binaryEncoder =
                        EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);

                DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(data.getSchema());
                datumWriter.write(data, binaryEncoder);

                binaryEncoder.flush();
                byteArrayOutputStream.close();

                result = byteArrayOutputStream.toByteArray();
                byteArrayOutputStream.close();
                logger.debug("serialized data='{}'" +  DatatypeConverter.printHexBinary(result));
            }
            return result;
        } catch (IOException ex) {
            throw new SerializationException(
                    "Can't serialize data='" + data + "' for topic='" + topic + "'", ex);
        }
    }

desirializer代码: -

    @Override
    public T deserialize(String topic, byte[] data) {
        try {
            T result = null;

            if (data != null) {
                logger.debug("data='{}'" + DatatypeConverter.printHexBinary(data));

                DatumReader<GenericRecord> datumReader =
                        new SpecificDatumReader<>(targetType.newInstance().getSchema());
                Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);

                result = (T) datumReader.read(null, decoder);
                logger.debug("deserialized data='{}'" + result);                
            }
            return result;
        } catch (Exception ex) {
            throw new SerializationException(
                    "Can't deserialize data '" + Arrays.toString(data) + "' from topic '" + topic + "'", ex);
        }
    }

架构文件: -

{"namespace": "com.test",
  "type": "record",
  "name": "Measures",
  "fields": [  
    {"name": "transactionDate", "type": ["int", "null"], "logicalType" : "date" }
   ]
}

并且这两个在生产者和消费者配置中被定义为序列化器和反序列化器类。

1 个答案:

答案 0 :(得分:0)

我没有使用过Apace Avro和Apache Kafka,但也许这会有所帮助......

  

我可以发送和接收Apache Avro的日期类型

查看维基百科页面,Avro中没有定义Date类型:

  

使用JSON定义Avro架构。模式由基本类型(null,boolean,int,long,float,double,bytes和string)和复杂类型(record,enum,array,map,union和fixed)组成。

JSON also lacks date-time types

ISO 8601

在没有提供日期时间支持的情况下,我建议使用标准ISO 8601格式将日期时间值序列化为文本。这些格式设计实用:易于通过机器解析,并且易于跨文化阅读,同时避免歧义。

对于仅限日期的值,格式为YYYY-MM-DD。 2018年1月23日将是2018-01-23

java.time

java.time 类在解析/生成字符串时默认使用ISO 8601格式。

LocalDate类表示没有时间且没有时区的仅限日期的值。

LocalDate.of( 2018 , Month.JANUARY , 23 )
         .toString()                              // Generating a string in standard format.
  

2018年1月23日

LocalDate ld = LocalDate.parse( "2018-01-23" ) ;  // Parsing a string in standard format.

计数-从历元

我不建议将日期时间值跟epoch reference计算。但如果您决定采用这种方式, java.time 类可以提供帮助。

1970-01-01的纪元参考日期定义为常数LocalDate.EPOCH

获取该纪元参考后的天数。

long daysSinceEpoch = ld.toEpochDay() ;
  

17554

解析自纪元以来的天数。在1970-01-01结果中添加17,554天,结果是2018-01-23。

LocalDate ld = LocalDate.ofEpochDay( 17_554L ) ;  // 1970-01-01 + 17,554 days = 2018-01-23

你可以看到为什么我不推荐这种从纪元开始的方法:阅读和调试2018-01-23比解密17554容易得多。

约达时间

Apache Avro包含adapter class for Joda-Time种类型(ticket AVRO-1672)。我不知道是否为 java.time 类型构建了这样的适配器。

Joda-Time项目是Java内置的 java.time 框架的前身。该项目现在处于维护模式,作者建议迁移到java.time类。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore