我可以通过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" }
]
}
并且这两个在生产者和消费者配置中被定义为序列化器和反序列化器类。
答案 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格式将日期时间值序列化为文本。这些格式设计实用:易于通过机器解析,并且易于跨文化阅读,同时避免歧义。
对于仅限日期的值,格式为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年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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; 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。