java - 是否有 Avro 的 "duration"逻辑类型的 API 实现?

标签 java avro duration

当前的 Apache Avro (1.8.2) 文档提到了“duration”逻辑类型:

A duration logical type annotates Avro fixed type of size 12, which stores three little-endian unsigned integers that represent durations at different granularities of time. The first stores a number in months, the second stores a number in days, and the third stores a number in milliseconds.

虽然这一切都说得通,但我无法在 .Net 或 Java 库中找到实际的实现。 documentation for logical types清楚地列出除持续时间(日期、时间-毫秒、时间-微量、时间戳-毫秒和时间戳-微量)之外的所有逻辑类型。

相应地在我的 Avro 架构中定义了“持续时间”:

{
    "type": "record",
    "name": "DataBlock",
    "fields": [
    {
        "name": "duration",
        "type": {
            "type": "fixed",
            "name": "DataBlockDuration",
            "size": 12
        }
    }]
}

在 .Net 中(请原谅 VB),我必须手动序列化持续时间:

Dim ret(11) As Byte
Dim months = BitConverter.GetBytes(duration.Months)
Dim days = BitConverter.GetBytes(duration.Days)
Dim milliseconds = BitConverter.GetBytes(duration.Milliseconds)

Array.Copy(months, 0, ret, 0, 4)
Array.Copy(days, 0, ret, 4, 4)
Array.Copy(milliseconds, 0, ret, 8, 4)

在 Java 中反序列化时,我必须通过这样做转换为 org.joda.time.Period:

IntBuffer buf = ByteBuffer
                  .wrap(dataBlock.getDuration().bytes())
                  .order(ByteOrder.LITTLE_ENDIAN)
                  .asIntBuffer();

Period period = Period
                  .months(buf.get(0))
                  .withDays(buf.get(1))
                  .withMillis(buf.get(2));

是我遗漏了什么,还是 Avro 团队编写了规范但忘记实现了?似乎这种数据类型必须在没有任何 Avro API 帮助的情况下实现。

最佳答案

乔达时间

Joda-Time项目现在在maintenance mode ,团队建议迁移到 java.time类。概念相似,因为这两个项目都是由同一个人 Stephen Colebourne 领导的。

java.time

java.time 框架提供了两个独立的类来表示独立于时间轴的时间跨度:

  • Period
    若干年、月和日。
  • 持续时间
    天数(与日历无关的通用 24 小时时间 block )、小时、分钟、秒和小数秒(纳秒)。

您可以将前两个数字用作 Period , 第三个数字代表 Duration .

Period p = Period.ofMonths( months ).plusDays( days ) ;
Duration d = Duration.ofMillis( millis ) ;

您可能想要 normalize the years & months of the Period目的。例如,“15 个月”的时间段将标准化为“1 年零 3 个月”。

Period p = Period.ofMonths( months ).plusDays( days ).normalized() ;

ISO 8601

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

对于一段时间或持续时间,这意味着使用 PnYnMnDTnHnMnS格式。 P 标记开始,T 将任何年-月-日与任何时-分-秒分开。例如,“P3Y6M4DT12H30M5S”表示时长为“三年六个月四天十二小时三十分五秒”。

要生成这样的字符串,只需在PeriodDuration 上调用toString。要解析,请调用 parse

Avro 中的奇怪概念

Avro 的持续时间概念(月 + 天 + 毫秒)对我来说似乎很奇怪。最大的问题是将年-月-日与时-分-秒混合使用几乎没有任何实际意义(想想看)。跟踪几个月而不是几年是令人惊讶的。

org.threeten.extra.PeriodDuration

如果您坚持要将年-月-日与时-分-秒合并,请考虑添加 ThreeTen-Extra库到您的项目。它提供了一个 PeriodDuration类。

PeriodDuration pd = PeriodDuration.of( p , d ) ;  // Pass `Period` and `Duration` objects as covered above.

同样,您可能希望调用 normalizedStandardDaysnormalizedYears .


关于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。该项目是 future 可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 Interval , YearWeek , YearQuarter , 和 more .

关于java - 是否有 Avro 的 "duration"逻辑类型的 API 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49992244/

相关文章:

csv - 创建一个 HIVE 表,根据列中的值从 HDFS 中的 .csv 中过滤数据

java - Joda Time : Formatting with multiple formats with single Formatter

python - 解析 xs :duration datatype into a Python datetime. timedelta 对象?

javascript - 索引超出范围 this.buf.utf8Slice

java - 如何从文件夹结构中获取文件列表

java - 如何在java中实现int in/out params

java - 在 JSF 中,拥有 ui :repeater inside a h:dataTable 是否有效

hadoop - java.io.IOException : Not a data file 异常

android - 在 Kotlin 中解析持续时间字符串

java - Controller 中的断言与如果