[英]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框架提供了兩個單獨的類來表示未附加到時間軸的時間跨度:
Period
Duration
您可以將前兩個數字用作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() ;
解析/生成字符串時, java.time類使用標准的ISO 8601標准格式。
對於一段時間或持續時間,這意味着使用PnYnMnDTnHnMnS
格式。 P
標志着開始, T
將任何年 - 月 - 天與任何小時 - 分鍾 - 秒分開。 例如,“P3Y6M4DT12H30M5S”表示“三年,六個月,四天,十二小時,三十分鍾和五秒”的持續時間。
要生成這樣的字符串,只需在Period
或Duration
上調用toString
。 要解析,請調用parse
。
Avro的持續時間概念(月+天+毫秒)對我來說似乎很奇怪。 最大的問題是,將數月 - 月 - 天與小時 - 分鍾 - 秒混合很少有任何實際意義(考慮一下)。 跟蹤數月而非數年是令人驚訝的。
org.threeten.extra.PeriodDuration
如果您堅持要將年 - 月 - 天與小時 - 分 - 秒合並,請考慮將ThreeTen-Extra庫添加到項目中。 它提供了PeriodDuration
類。
PeriodDuration pd = PeriodDuration.of( p , d ) ; // Pass `Period` and `Duration` objects as covered above.
同樣,您可能希望調用normalizedStandardDays
和normalizedYears
。
java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊遺留日期時間類,如java.util.Date
, Calendar
和SimpleDateFormat
。
現在處於維護模式的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的試驗場。 您可以在這里找到一些有用的類,比如Interval
, YearWeek
, YearQuarter
,和更多 。
根據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來規避問題的方法很好,因為:
Period
-class可以在幾個月,幾天和幾毫秒內完全映射Avro-spec持續時間(並且使用Avro規范要求的無符號整數,總是正持續時間對於避免混合符號的奇數時段也是一件好事)。 我所知道的Joda-Time的可能替代方案:
PeriodDuration
(參見Basil Bourque的答案) Threeten-Extra-class比Joda級別具有更少的功能(完全沒有本地化,減少了ISO-8601合規性等),但在特殊的Avro相關場景中可能仍然足夠你,而Time4J級別更多比Joda提供的功能(在ISO兼容性,格式化,解析,規范化等方面)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.