代码之家  ›  专栏  ›  技术社区  ›  Atul Ojha

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

  •  1
  • Atul Ojha  · 技术社区  · 7 年前

    是否有我可以发送和接收日期类型的 Apache Avro . 我没能在这上面找到任何东西。我发现只有在模式中使用int和logicalType的日期。但这会导致接收器端出现另一个int。我还得把它改成日期。

    我正在尝试从 Apache 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);
            }
        }
    

    Desiralizer代码:-

        @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 回复  |  直到 7 年前
        1
  •  0
  •   Basil Bourque    7 年前

    我没有使用Apace Avro或Apache Kafka,但这可能会有所帮助

    是否可以使用Apache Avro发送和接收日期类型

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

    Avro模式是使用JSON定义的。模式由基本类型(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语言时间

    这个 Java语言时间 类在解析/生成字符串时默认使用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语言时间 课程可以提供帮助。

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

    获取自该历元引用以来的天数。

    long daysSinceEpoch = ld.toEpochDay() ;
    

    17554

    分析自epoch以来的天数。在1970年1月1日的基础上增加17554天,结果是2018年1月23日。

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

    您可以看到为什么我不推荐使用epoch方法进行计数:读取和调试 2018-01-23 比破译容易得多 17554 .

    Joda时间

    Apache Avro包括 adapter class for Joda-Time 类型( ticket AVRO-1672 ). 我不知道是否为 Java语言时间 类型尚未确定。

    Joda Time项目是 Java语言时间 Java内置的框架。该项目现在处于维护模式,作者建议迁移到java。时间类。


    关于 Java语言时间

    这个 java.time 框架内置于Java 8及更高版本中。这些课程取代了烦人的旧课程 legacy 日期时间类,如 java.util.Date , Calendar ,& SimpleDateFormat .

    这个 Joda-Time 项目,现在处于 maintenance mode ,建议迁移到 java.time 课程。

    要了解更多信息,请参阅 Oracle Tutorial . 并搜索堆栈溢出以获得许多示例和解释。规格为 JSR 310 .

    您可以交换 Java语言时间 对象直接与数据库连接。使用 JDBC driver 符合 JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 课程。

    从何处获取java。时间课程?

    这个 ThreeTen-Extra project扩展了java。额外上课的时间。该项目是java未来可能添加内容的试验场。时间您可以在这里找到一些有用的类,例如 Interval , YearWeek , YearQuarter more .