Java 8 java.time.LocalDate
允许您根据Dates
,Year
和Month
定义DayOfMonth
,而不使用时区。它通过没有基础Long
表示来实现这一点,而是Year
,Month
和DayOfMonth
。这具有逻辑意义,因为当存储Date
时,您不希望观看者将其解释为基于时区的不同日期。
java.sql.Date
是Long
表示的“瘦包装”,这是spark中唯一支持的日期类型。
因此,我的问题是,您如何确保将Date
存储在Spark数据集中并将其序列化为磁盘(即)镶木地板文件,并将其读取并解释为正确的日期而不传递时区信息?
示例:
我可以解析英格兰的字符串"2016-01-01 02:00"
(GMT + 0)。我实际想要存储的是一天/月/年。但由于它是java.sql.Date
,它将在下午2点存储基础unixtime。然后我将其序列化,并且美国东海岸的某个人将其捡起并繁荣起来。它现在是"2016-12-31 21:00"
。如果我知道时区,我会知道它实际上是"2016-01-01 02:00"
。
如果java.sql.Date
是无时区且仅使用UTC,我可以理解,但它使用LocalTimeZone
进行解释。
因此,如何存储因DateTime
存储unix然后使用java.sql.Date
解释LocalTimeZone
而无法解释错误的Date
?< / p>
答案 0 :(得分:1)
java.sql.Date
没有时区信息,您可以从documentation中的主构造函数签名中看到。
如果时间戳存储在某个没有时区信息的地方,则需要以某种方式在带外传递此信息。最安全的选择是将其存储为UTC时间,因为Unix时代是一个长期的惯例,很容易就许多系统的兼容性达成一致。
由于Spark已经公开了处理java.sql.Date
和java.sql.Timestamp
的工具,我建议你坚持使用{以及org.spark.sql.functions
中的预定义函数。)
遗憾的是,没有办法阻止误导客户端使用错误的解释反序列化值。您可以将时区信息作为第二列的一部分传递,但没有任何东西可以阻止用户仅获取存储在第一列中的值并假设它是本地日期(无论“本地”在运行时上下文中是什么意思)。