簡體   English   中英

是否存在Avro的“持續時間”邏輯類型的API實現?

[英]Is there an API implementation of Avro's “duration” logical type?

當前的Apache Avro(1.8.2)文檔提到了“ 持續時間 ”邏輯類型:

持續時間邏輯類型注釋大小為12的Avro固定類型,它存儲三個小端無符號整數,表示不同粒度時間的持續時間。 第一個以月為單位存儲數字,第二個以天為單位存儲數字,第三個以毫秒為單位存儲數字。

雖然這一切都有意義,但我無法在.Net或Java庫中找到實際的實現。 邏輯類型文檔清楚地列出了除持續時間(日期,時間 - 毫秒,時間 - 微觀,時間戳 - 毫秒和時間戳 - 微觀)之外的每個邏輯類型。

“持續時間”在我的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項目現在處於維護模式 ,團隊建議遷移到java.time類。 概念是相似的,因為兩個項目都由同一個人Stephen Colebourne領導。

java.time

java.time框架提供了兩個單獨的類來表示未附加到時間軸的時間跨度:

  • Period
    幾年,幾個月和幾天。
  • Duration
    幾天(與日歷無關的通用24小時時間段),小時,分鍾,秒和小數秒(納秒)。

您可以將前兩個數字用作Period ,將第三個數字用作Duration

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

您可能希望規范化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及更高版本中。 這些類取代了麻煩的舊遺留日期時間類,如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參閱Oracle教程 並搜索Stack Overflow以獲取許多示例和解釋。 規范是JSR 310

您可以直接與數據庫交換java.time對象。 使用符合JDBC 4.2或更高版本的JDBC驅動程序 不需要字符串,不需要java.sql.*類。

從哪里獲取java.time類?

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目是未來可能添加到java.time的試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

根據Apache問題跟蹤器AVRO-2123 ,已指定邏輯持續時間類型但尚未實現。

所以,是的,Apache團隊編寫了規范,但忘記了在這個細節中實現它。

我還在Avro-version 1.8.2中搜索了解壓縮的jar文件以獲取joda-library的任何導入,並且只找到了org.apache.avro.data.TimeConversions類,它為其他邏輯類型獲取了一些轉換,例如“date” (映射到org.joda.time.LocalDate )等但不適用於Joda-class Period

似乎你通過使用Period -class of Joda來規避問題的方法很好,因為:

  • Avro仍然使用Joda-Time(雖然后者處於維護模式),
  • Period -class可以在幾個月,幾天和幾毫秒內完全映射Avro-spec持續時間(並且使用Avro規范要求的無符號整數,總是正持續時間對於避免混合符號的奇數時段也是一件好事)。

我所知道的Joda-Time的可能替代方案:

  • Threeten-Extra-Class PeriodDuration (參見Basil Bourque的答案)
  • Time4J-class net.time4j.Duration (我的lib)

Threeten-Extra-class比Joda級別具有更少的功能(完全沒有本地化,減少了ISO-8601合規性等),但在特殊的Avro相關場景中可能仍然足夠你,而Time4J級別更多比Joda提供的功能(在ISO兼容性,格式化,解析,規范化等方面)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM