全麵的看日期和時間戳在Apache火花™3.0
2020年7月22日 在工程的博客
Apache火花是一個非常受歡迎的工具,用於處理結構化和非結構化數據。時處理結構化數據,它支持許多基本數據類型,如整數、長,雙,字符串,等等。火花還支持更複雜的數據類型,如日期
和時間戳
開發人員,通常難以理解。在這篇文章中,我們將深入探究日期和時間戳的類型來幫助你完全理解他們的行為,以及如何避免一些常見的問題。總之,這個博客涵蓋了四個部分:
- 日期類型的定義和相關的日曆。它也涵蓋了火花3.0中的日曆開關。
- 時間戳的定義類型,以及它如何與時區。這也解釋了時區偏移決議的細節,和微妙的行為變化的新的時間API在Java 8中,由火花使用3.0。
- 公共api來構建日期和時間戳值在火花。
- 常見的陷阱和最佳實踐來收集日期和時間戳上的對象引發司機。
日期和日曆
的定義日期
的很簡單:這是一個組合嗎一年,月和一天領域,如(年= 2012,月= 12日天= 31)。然而,的值年、月和日領域限製,所以日期值在現實世界中是一個有效的一天。例如,必須從1到12個月的價值,必須從1天的價值28/29/30/31(取決於年和月),等等。
這些約束之一是由許多可能的日曆。其中一些隻用於特定區域,如陰曆。他們中的一些人隻是用於曆史,像公曆。此時,公曆是事實上的國際標準,幾乎在世界各地用於民事用途。它是在1582年引入的,擴展為支持日期在1582年之前。這個擴展的日曆被稱為預期的公曆。
從3.0版開始,火花使用預期的公曆,已經被其他數據係統(比如熊貓,R和Apache箭頭。在火花3.0之前,它使用的組合朱利安和公曆:日期在1582年之前,使用公曆,1582年後使用公曆日期。這是繼承了遺產java.sql.Date
API,它在Java 8所取代java.time.LocalDate
使用預期的公曆。
值得注意的是,不考慮時區的日期類型。
時間戳和時區
的時間戳
與新字段類型擴展了日期類型:小時,一分鍾,第二個(可以有小數部分)和一起全球時區(會話作用域)。它定義了一個具體的時間即時在地球上。例如,(年= 2012,月= 12日天= 31小時= 23分鍾= 59歲,第二個= 59.123456)與會話時區UTC + 01:00。當編寫時間戳值非文本數據來源如拚花,隻是瞬間的值(比如在UTC時間戳)沒有時區信息。如果你寫和閱讀時間戳值與不同的會話時區,您可能會看到不同的小時/分鍾/秒字段值,但它們實際上是相同的具體時間。
小時,分鍾和第二領域標準範圍:0-23小時0-59分鍾和秒。火花支持毫秒微秒級精度。分數的有效範圍從0到999999微秒。
在任何具體的時刻,我們可以觀察到許多不同的價值觀的掛鍾,根據時區。
反之,任何價值在牆壁上的時鍾可以代表許多不同的時間瞬間。時區偏移可以讓我們明確地將本地時間戳綁定到一個瞬間的時間。通常被定義為時區偏移補償在數小時內從格林威治標準時間(GMT)UTC + 0(協調世界時)。這樣一個時區信息消除了歧義的代表,但它是最終用戶的不便。用戶更喜歡指出位置等世界各地美國/ Los_Angeles
或歐洲/巴黎
。
這些額外的抽象級別從區補償使生活更輕鬆,但有其自己的問題。例如,我們現在必須保持一個特殊時區數據庫時區名稱映射到補償。由於火花在JVM上運行,它代表映射到Java標準庫,它裝載的數據互聯網地址分配機構的數據庫時區(IANA TZDB)。此外,Java的標準庫中的映射機製有一些細微的差別,影響引發的行為。下麵我們關注一些細微的差別。
自Java 8, JDK暴露出了一個新的API操縱日期-時間和時區偏移決議,並引發遷移到這個新的API 3.0版本中。雖然補償時區名稱的映射具有相同的來源,IANA TZDB,實現不同的Java 8和更高的與Java 7。
作為一個例子,讓我們看看一個時間戳在1883年之前
美國/ Los_Angeles
時區:1883-11-10就是
。今年從別人的與眾不同之處在於11月18日,1883年,所有北美鐵路轉向了一種新標準時間係統,今後治理他們的時間表。使用Java 7次API,我們可以獲取時區偏移在當地時間戳喂飼:
scala > java.time.ZoneId.systemDefaultres0: java.time。美國/ Los_Angeles ZoneId =scala > java.sql.Timestamp.valueOf (“1883-11-10”就是)。getTimezoneOffset /60.0res1:雙=8.0
Java 8 API函數返回一個不同的結果:
scala > java.time.ZoneId.of (“美國/ Los_Angeles”).getRules.getOffset (java.time.LocalDateTime.parse (“1883 - 11 - 10 - t00:00:00”))它:java.time。ZoneOffset = -07年:52:58
1883年11月18日之前,每天的時間是當地的物質,和大多數城市和城鎮使用某種形式的地方太陽時,由著名的鍾(在一座教堂的尖塔,例如,或在一個珠寶商的窗口)。這就是為什麼我們看到這樣一個奇怪的時區偏移量。
的例子演示了Java 8函數更精確,從IANA TZDB考慮曆史數據。切換到Java 8次API之後,火花3.0受益於改善自動和變得更精確的在如何解決時區偏移量。
如前所述,火花3.0還轉向的預期的公曆日期類型。這同樣適用於時間戳的類型。的ISO SQL: 2016標準聲明時間戳的有效範圍0001-01-01就是
來9999-12-31 23:59:59.999999
。火花3.0完全符合標準,支持所有的時間戳在這個範圍。比較2.4和更早的火花,我們應該突出下麵的子區間:
0001-01-01就是. .1582年-10年- - - - - -03 23:59:59.999999
。火花2.4使用公曆,不符合標準。火花3.0補丁問題,應用在內部運營預期的公曆時間戳等一年,月,日,等。由於不同的日曆,日期中存在的一些火花引發3.0中2.4是不存在的。例如,1000不是一個有效的日期,因為1000-02-29不是一個公曆閏年。同時,火花2.4解決時區名稱為這個時間戳區補償錯誤範圍。1582-10-04就是. .1582年-10年- - - - - -14 23:59:59.999999
。這是一個有效的本地時間戳在火花3.0中,與火花2.4不存在這樣的時間戳。1582-10-15就是. .1899-12-31 23:59:59.999999
。火花3.0解決時區偏移量從IANA TZDB正確使用曆史數據。2.4相比3.0火花,火花可能解決區域補償時區名稱錯誤在某些情況下,正如我們上麵顯示的例子。1900-01-01就是. .2036- - - - - -12- - - - - -31日23:59:59.999999
。3.0火花,火花2.4符合ANSI SQL標準和使用公曆日期-時間操作,如月的日子。2037-01-01就是. .9999- - - - - -12- - - - - -31日23:59:59.999999
。火花2.4可以解決時區偏移和特別是夏令時補償錯誤因為JDK的bug# 8073446。火花3.0不患有這種缺陷。
時區名稱映射到補償的一個方麵是重疊的本地時間戳,可以發生由於夏令時(DST)或切換到另一個標準時區偏移量。例如,在2019年11月3日,02:00:00
時鍾落後了1小時01:00:00
。本地時間戳
2019-11-03 01:30:00
美國/ Los_Angeles可以映射2019-11-03 01:30:00 UTC-08:00
或2019-11-03 01:30:00 UTC-07:00
。如果你不指定偏移量和設置時區名稱(例如,“美國2019-11-03 01:30:00 / Los_Angeles”
),火花3.0將抵消早些時候,通常對應於“夏天”。的behavior diverges from Spark 2.4 which takes the "winter" offset. In the case of a gap, where clocks jump forward, there is no valid offset. For a typical one-hour daylight saving time change, Spark will move such timestamps to the next valid timestamp corresponding to "summer" time.
從上麵的例子中,我們可以看到時區名稱的映射補償是模糊的,這不是一個對一個。情況下,當它是可能的,我們建議指定的時區偏移時時間戳,例如時間戳
“2019-11-03 01:30:00 UTC-07:00”
。
讓我們遠離區域名稱,以抵消映射,看看ANSI SQL標準。它定義了兩種類型的時間戳:
沒有時區的時間戳
或時間戳
本地時間戳(年,月,日,小時,分鍾,秒)。這些時間戳不綁定任何時區,實際上是掛鍾時間戳。時間戳和時區
——分區時間戳(年、月、日、小時、分鍾,第二,TIMEZONE_HOUR, TIMEZONE_MINUTE)。代表的時間戳在UTC時間區域+一個時區偏移(小時和分鍾數)的價值。
的時區偏移時間戳和時區
不影響時間戳代表的物理時間點,因為這是完全由的UTC時間即時其他時間戳組件。相反,時區偏移量僅影響的默認行為的時間戳值顯示,日期/時間分量提取(如。提取
),需要知道時區的其他操作,如添加幾個月時間戳。
火花SQL類型定義了時間戳時間戳與會話時區
的,這是一個組合字段(一年
,月
,一天
,小時
,一分鍾
,第二個
,會話TZ
)一年
通過第二個
字段確定一個時間即時UTC時間,和地點會話TZ
來自SQL配置spark.sql.session.timeZone
。會話時區可以設置為:
- 區抵消
“(+ | -)HH: mm”
。這種形式允許我們定義一個物理時間點明確。 - 時區名稱的形式區域ID
“區域/城市”
,如“美國/ Los_Angeles”
。這種形式的時區信息存在的一些問題,我們上麵描述的像重疊的本地時間戳。然而,明確每個UTC時間即時與一個時區抵消任何區域ID,因此,每個時間戳可以明確地區基於ID的時區轉換為時間戳與區域偏移量。
默認情況下,會話時區設置的默認時區Java虛擬機。
火花的時間戳與會話時區
是不同的:
沒有時區的時間戳
,因為這種類型的值可以映射到多個物理時間的瞬間,但是任何的價值時間戳與會話時區
即時是一個具體的物理時間。SQL類型可以通過使用一個模擬固定在所有會話時區偏移,例如UTC + 0。在這種情況下,我們可以考慮在UTC時間戳作為本地時間戳。時間戳和時區
,因為根據SQL標準列值的類型可以有不同的時區偏移量。,不支持SQL。
我們應該注意時間戳與全球相關(會話作用域)時區被火花不是新發明的SQL。rdbms如Oracle提供類似時間戳:與當地時區的時間戳。
創建日期和時間戳
火花SQL提供了一些方法來創建日期和時間戳值:
- 默認構造函數沒有參數:
CURRENT_TIMESTAMP ()
和當前日期()
。 - 從其他原始火花SQL類型等
INT
,長
,字符串
- 從外部類型像Python
datetime
或Java類java.time.LocalDate /即時
。 - 反序列化數據來源CSV、JSON、Avro,拚花,獸人或其他人。
這個函數MAKE_DATE
在火花3.0中引入的接受三個參數:一年
,月
今年,一天
月,使日期
價值。所有輸入參數是隱式轉換成INT
盡可能的類型。功能檢查結果預期的公曆日期是有效日期,否則它的回報零
。例如在PySpark:
> > >spark.createDataFrame (((2020年,6,26),(1000年,2,29日),(-44,1,1)),…(“Y”,“米”,' D ']).createTempView (“YMD”)> > >df = sql (“選擇make_date (Y, M, D)從YMD日期”)> > >df.printSchema ()根| - - -日期:日期(可空= true)
打印DataFrame內容,我們叫的顯示()
行動,將日期轉換為字符串的執行者和轉移司機的字符串輸出到控製台:
> >>df.show ()+- - - - - - - - - - - - +|日期|+- - - - - - - - - - - - +|2020年-06年-26年||零||-0044年-01年-01年|+- - - - - - - - - - - - +
同樣的,我們可以通過時間戳值MAKE_TIMESTAMP
功能。就像MAKE_DATE
日期字段,它執行相同的驗證,而且接受時間字段小時(0-23)
,分鍾(0-59)
和第二個(0-60)
。第二個
有類型小數
(精度= 8,規模= 6)因為秒可以通過微秒級精度的小數部分。例如在PySpark:
> >>df=spark.createDataFrame (((2020年,6,28,10,31日,30.123456),…(1582年,10,10,0,1,2.0001),(2019年,2,29日,9,29日,1.0)),…(“年”,“月”,“天”,“小時”,“一分鍾”,“第二”])> >>df.show ()+- - - - - + - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - +|一年|月|一天|小時|一分鍾|第二個|+- - - - - + - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - +|2020年|6|28|10|31日|30.123456||1582年|10|10|0|1|2.0001||2019年|2|29日|9|29日|1.0|+- - - - - + - - - + - - - + - - - + - - - - - - - - - - - - - - - - - - +> >>ts=df。selectExpr (“make_timestamp(年,月,日,小時,分鍾,秒)make_timestamp”)> >>ts.printSchema ()根|——MAKE_TIMESTAMP:時間戳(nullable = true)
作為我們的日期,讓我們打印的內容ts
DataFrame使用顯示()
行動。以類似的方式,顯示()將時間戳轉換為字符串但現在考慮會話時區配置定義的SQLspark.sql.session.timeZone
。我們將看到在下麵的例子。
> >>ts.show (截斷=假)+- - - - - - - - - - - - - - - - - - - - - - - - - - - - +|MAKE_TIMESTAMP|+- - - - - - - - - - - - - - - - - - - - - - - - - - - - +|2020年-06年-28年10:31日:30.123456||1582年-10年-10年00:01:02.0001||零|+- - - - - - - - - - - - - - - - - - - - - - - - - - - - +
火花不能創建最後一個時間戳,因為這不是有效日期:2019年不是閏年。
您可能注意到,我們不提供任何時區信息在上麵的例子中。在這種情況下,火花時區從SQL配置spark.sql.session.timeZone
它適用於函數調用。你也可以選擇一個不同的時區通過它的最後一個參數MAKE_TIMESTAMP
。這裏有一個例子在PySpark:
> > >df = spark.createDataFrame (((2020年,6,28,10,31日,30.,UTC的),…(1582年,10,10,0,1,2,“美國/ Los_Angeles”),…(2019年,2,28,9,29日,1,“歐洲/莫斯科”)),…(“年”,“月”,“天”,“小時”,“一分鍾”,“第二”,' TZ '])> > >df = df.selectExpr (“make_timestamp(年、月、日、小時、分鍾,第二,TZ) make_timestamp”)> > >df = df.selectExpr (“date_format (MAKE_TIMESTAMP yyyy-MM-dd HH: mm: SS VV) TIMESTAMP_STRING”)> > >df.show(截斷=假)+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +| TIMESTAMP_STRING |+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +|2020年-06 -2813:31日:00歐洲/莫斯科||1582年- - - - - -10- - - - - -1010:24:00歐洲/莫斯科||2019年-02 -2809:29日:00歐洲/莫斯科|+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
為例說明,火花考慮指定時區但調整所有本地時間戳會話時區。原來的時區傳遞到MAKE_TIMESTAMP
功能將丟失,因為時間戳與會話時區
假設所有值類型屬於一個時區,它甚至不存儲一個時區每值。根據的定義時間戳與會話時區
,引發當地商店在UTC時間戳時區,並使用會話時區而提取日期-時間字段或將時間戳轉換為字符串。
同時,可以建造的時間戳長
通過鑄造類型。如果一個長
列包含時代以來的秒數1970-01-01 00:00:00Z,可以把它轉換為SQL的火花時間戳
:
火花- - - - - -sql>選擇投(-123456789作為時間戳);1966年-02年-02年05年:26:51
不幸的是,這種方法不允許我們指定秒的小數部分。在未來,火花SQL提供特殊功能將從秒時間戳,毫秒、微秒時代:timestamp_seconds ()
,timestamp_millis ()
和timestamp_micros ()
。
另一種方法是構建日期和時間戳的值字符串
類型。我們可以讓文字使用特殊的關鍵詞:
火花- - - - - -sql>選擇時間戳“2020-06-28 22:17:33.123456歐洲/阿姆斯特丹的,日期“2020-07-01”;2020年-06年-28年23:17:33.1234562020年-07年-01年
或通過鑄造,我們可以申請列中的所有值:
火花- - - - - -sql>選擇投(“2020-06-28 22:17:33.123456歐洲/阿姆斯特丹的作為時間戳),投(“2020-07-01”作為日期);2020年-06年-28年23:17:33.1234562020年-07年-01年
輸入時間戳字符串解釋為本地時間戳在指定的時區或會話時區如果省略時區在輸入字符串。與不尋常的模式可以被轉換成字符串使用的時間戳to_timestamp ()
函數。描述的支持模式Datetime模式格式化和解析:
火花- - - - - -sql>選擇to_timestamp (“28/6/2020 22.17.33”,“dd / M / yyyy HH.mm.ss”);2020年-06年-28年22:17:33
函數的行為類似於投
如果你不指定任何模式。
可用性,火花SQL識別特殊的字符串值以上方法接受一個字符串並返回一個時間戳和日期:
- 時代是一個別名日期“1970-01-01”或時間戳
“1970-01-01 00:00:00Z”
- 現在是當前時間戳或會話時區的日期。在一個查詢中它總是產生同樣的結果。
- 今天是當前日期的開始的嗎
時間戳
類型或隻是當前日期日期
類型。 - 明天是第二天的開始時間戳或隻是第二天嗎
日期
類型。 - 昨天前一天是目前的一個或的開始
時間戳
類型。
例如:
火花- - - - - -sql>選擇時間戳“昨天”,時間戳“今天”,時間戳“現在”,時間戳“明天”;2020年-06年-27年00:00:002020年-06年-28年00:00:002020年-06年-28年23:07年:07.182020年-06年-29年00:00:00火花- - - - - -sql>選擇日期“昨天”,日期“今天”,日期“現在”,日期“明天”;2020年-06年-27年2020年-06年-28年2020年-06年-28年2020年-06年-29年
火花的特性之一是創造數據集
從現有的外部對象的集合在司機身邊,並創建相應的列類型。火花將外部類型的實例轉換為語義等價的內部表示。PySpark允許創建一個數據集
與日期
和時間戳
列從Python集合,例如:
> > >進口datetime> > >df = spark.createDataFrame (((datetime.datetime (2020年,7,1,0,0,0),…datetime.date (2020年,7,1)]、[“時間戳”,“日期”])> > >df.show ()+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +| | |日期時間戳+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +|2020年07-0100:00:00|2020年07-01 |+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
PySpark Python的datetime對象轉換為內部火花在驅動端使用SQL表示係統時區,可以引發不同的會話時區設置spark.sql.session.timeZone
。內部價值不包含原始的時區信息。未來在並行操作日期和時間戳值將隻考慮火花SQL會話時區顯示時間戳與會話時區
類型定義。
以類似的方式為我們演示了以上Python集合,火花承認以下類型為外部日期時間類型在Java / Scala api:
- java.sql.Date和java.time.LocalDate作為external types for Spark SQL's DATE type
- java.sql.Timestamp和java.time.Instantfor the TIMESTAMP type.
是有區別的java.sql。*
和java.time。*
類型。的java.time.LocalDate
和java.time.Instant
被添加在Java 8,類型是基於預期的公曆,使用相同的日曆,火花從版本3.0。的java.sql.Date
和java.sql.Timestamp
下麵還有一個日曆-混合日曆(Julian +以來格雷戈裏1582-10-15
),這是一樣的遺留火花3.0之前版本所使用的日曆。由於不同的日曆係統,火花在轉換執行額外的操作內部引發SQL表示,從一個日曆和變基輸入日期/時間戳到另一個地方。現代時間戳的變基操作有一個小的開銷在1900年之後,它可以更重要的時間戳。
下麵的例子顯示了從Scala集合時間戳。在第一個示例中,我們建立一個java.sql.Timestamp
從一個字符串對象。的返回對象的值
方法解釋輸入字符串作為本地時間戳在JVM默認時區,可以引發不同的會話時區。如果您需要構建的實例java.sql.Timestamp
或java.sql.Date
在特定的時區,我們推薦一看java.text.SimpleDateFormat
(及其方法setTimeZone)或java.util.Calendar
。
scala>Seq (java.sql.Timestamp。返回對象的值("2020-06-29 22:41:30"),新java.sql.Timestamp (0).toDF (ts)。顯示(假)+- - - - - - - - - - - - - - - - - - - +|ts|+- - - - - - - - - - - - - - - - - - - +|2020年-06年-29年22:41:30.||1970年-01年-01年03:00:00|+- - - - - - - - - - - - - - - - - - - +scala>Seq (java.time.Instant.ofEpochSecond (-12219261484L)、java.time.Instant.EPOCH) .toDF (ts)。顯示+- - - - - - - - - - - - - - - - - - - +|ts|+- - - - - - - - - - - - - - - - - - - +|1582年-10年-15年11:12:13||1970年-01年-01年03:00:00|+- - - - - - - - - - - - - - - - - - - +
同樣的,我們可以製造一個約會之列的集合java.sql.Date
或java.LocalDate
。並行化的java.LocalDate
實例是完全獨立的火花的會話時區或JVM默認時區,但我們不能說相同的並行化java.sql.Date
實例。有細微差別:
java.sql.Date
JVM實例代表當地日期默認時區的司機- 對於正確轉換引發SQL價值觀,JVM默認時區的司機和執行人必須相同。
scala>Seq (java.time.LocalDate.of (2020年,2,29日),java.time.LocalDate.now) .toDF(“日期”)。顯示+- - - - - - - - - - - +|日期|+- - - - - - - - - - - +|2020年-02年-29年||2020年-06年-29年|+- - - - - - - - - - - +
為了避免任何日曆和時區相關問題,我們建議Java 8類型java.LocalDate /即時
並行化外部類型的Java / Scala集合的時間戳或日期。
收集日期和時間戳
反向操作並行化是收集日期和時間戳從執行人回到司機並返回外部類型的集合。對於上麵的例子,我們可以把DataFrame回到司機通過收集()
行動:
> >>df.collect ()(行(時間戳=datetime.datetime (2020年,7,1,0,0),日期=datetime.date (2020年,7,1)))
火花轉移內部的日期和時間戳列值隨著時間的瞬間在UTC時間區從執行者到司機,並執行轉換到Python datetime對象係統時區的司機,不使用火花SQL會話時區。收集()
不同於顯示()
行動前一節中描述。顯示()
使用會話時區而將時間戳轉換為字符串,並收集了字符串的司機。
在Java和Scala api,火花執行以下默認轉換:
- SQL的火花
日期
值轉換為實例java.sql.Date
。 - 時間戳轉換為實例
java.sql.Timestamp
。
這兩個轉換都表現在JVM默認時區的司機。這樣,相同的日期-時間字段,我們可以得到通過Date.getDay ()
,getHour ()
等,通過引發SQL函數一天
,小時
JVM,默認時區的司機和會話時區執行者應該是相同的。
同樣的日期/時間戳java.sql.Date /時間戳
火花3.0執行重新從預期的公曆混合日曆(Julian +格雷戈裏)。這個操作是幾乎免費的現代日期(1582年之後)和時間戳(1900年之後),但它可能帶來一些開銷古老的日期和時間戳。
我們可以避免這種calendar-related問題,讓火花返回java.time
類型,添加自Java 8。如果我們設置SQL配置spark.sql.datetime.java8API.enabled
真實的,Dataset.collect ()
行動將返回:
java.time.LocalDate
火花SQL的日期
類型java.time.Instant
火花SQL的時間戳
類型
現在轉換不遭受calendar-related問題,因為Java 8類型和火花SQL 3.0都是基於預期的公曆。的收集()
行動並不依賴於JVM默認時區。時間戳轉換不依賴於時區。關於日期轉換,它使用會話時區從SQL配置spark.sql.session.timeZone
。例如,讓我們看一個數據集日期
和時間戳
列,JVM設置默認時區歐洲/莫斯科,但會話時區美國/ Los_Angeles
。
scala>java.util.TimeZone.getDefaultres1: java.util.TimeZone=sun.util.calendar.ZoneInfo [id=“歐洲/莫斯科”,……)scala>spark.conf.get (“spark.sql.session.timeZone”)它:字符串=美國/Los_Angelesscala>df.show+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +|時間戳|日期|+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +|2020年-07年-01年00:00:00|2020年-07年-01年|+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
的顯示()
行動打印在會話時的時間戳美國/ Los_Angeles
,但是如果我們收集的數據集,它將轉換為java.sql.Timestamp
和打印,歐洲/俄羅斯
由toString
方法:
scala > df.collect ()res16:數組[org.apache.spark.sql。行]=數組([2020年- - - - - -07年- - - - - -0110:00:00。0,2020年- - - - - -07年- - - - - -01])scala > df.collect () (0).getAs [java.sql.Timestamp] (0).toStringres18:java.sql。時間戳=2020年- - - - - -07年- - - - - -0110:00:00。0
實際上,本地時間戳2020-07-01就是2020 - 07 - 01 t07:00:00z UTC。我們可以觀察到,如果我們使Java 8 API和收集數據集:
scala > df.collect ()res27:數組[org.apache.spark.sql。行]=數組([2020年- - - - - -07年-01 t07:00:00 z,2020年- - - - - -07年- - - - - -01])
的java.time.Instant
對象可以被轉換成任何本地時間戳之後獨立地從全球JVM時區。這是一個的優點java.time.Instant
在java.sql.Timestamp
。前一個需要改變全球JVM設置,影響其他時間戳在同一JVM。因此,如果您的應用程序進程日期或時間戳在不同的時區,和應用程序不應該互相衝突而收集數據通過Java / Scala司機Dataset.collect ()
API,我們建議切換到Java 8 API使用SQL配置spark.sql.datetime.java8API.enabled
。
結論
在這篇文章中,我們描述了火花SQL日期
和時間戳
類型。我們展示了如何構建與其他原始日期和時間戳列火花SQL類型和外部Java類型,以及如何收集日期和時間戳列回到司機為外部Java類型。3.0版本以來,火花從混合日曆,將朱利安和公曆日曆、預期的公曆(見火星- 26651更多的細節)。這允許火花消除許多問題如我們前麵了。為了向後兼容以前的版本中,火花仍然返回時間戳在混合日曆和日期(java.sql.Date
和java.sql.Timestamp
從收集喜歡的行為)。為了避免日曆和時區的分辨率問題使用Java / Scala的收集動作時,Java 8通過SQL API可以啟用配置spark.sql.datetime.java8API.enabled
。今天試一下免費磚7.0作為我們的磚運行時的一部分。