有没有我可以发送和接收日期类型与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" }
]
}
这两个只是在生产者和消费者配置中被定义为序列化器和反序列化器类。
我没有使用Apace Avro和Apache Kafka,但也许这会有所帮助......
我可以发送和接收Apache Avro的日期类型
查看维基百科页面,Avro中没有定义Date
类型:
Avro架构使用JSON定义。模式由基本类型(null,boolean,int,long,float,double,bytes和string)和复杂类型(记录,枚举,数组,映射,联合和固定)组成。
JSON also lacks date-time types。
在没有提供日期时间支持的情况下,我建议使用标准的ISO 8601格式将日期时间值序列化为文本。这些格式设计实用:易于通过机器解析,并且易于跨文化阅读,同时避免歧义。
对于仅日期值,格式为YYYY-MM-DD。 2018年1月23日将是2018-01-23
。
在解析/生成字符串时,java.time类默认使用ISO 8601格式。
LocalDate
类表示没有时间且没有时区的仅日期值。
LocalDate.of( 2018 , Month.JANUARY , 23 )
.toString() // Generating a string in standard format.
2018-01-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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
现在在Joda-Time的maintenance 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的试验场。你可能会在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
和more。