我正试图将字符串更改为时间戳,但在我的区域中,3月的最后一个星期日(凌晨2:00至3:00(不存在并返回null。示例:
scala> spark.sql("select to_timestamp('20220327 021500', 'yyyyMMdd HHmmss') from *").show(1)
+--------------------------------------------------+
|to_timestamp('20220327 021500', 'yyyyMMdd HHmmss')|
+--------------------------------------------------+
| null|
+--------------------------------------------------+
only showing top 1 row
scala> spark.sql("select to_timestamp('20220327 031500', 'yyyyMMdd HHmmss') from *").show(1)
+--------------------------------------------------+
|to_timestamp('20220327 031500', 'yyyyMMdd HHmmss')|
+--------------------------------------------------+
| 2022-03-27 03:15:00|
+--------------------------------------------------+
only showing top 1 row
一个解决方案可能是在这些天的凌晨2:00到3:00之间增加一个小时,但我不知道如何实现这个解决方案
我无法更改数据源
我能做什么?
感谢
编辑
官方文件显示:
在Spark 3.1中,从_unix_time,unix_timestamp,到_unix_timestamp,如果指定的日期时间模式,to_timestamp和to_date将失败无效。在Spark 3.0或更早版本中,结果为NULL。(1(
让我们考虑下面的数据帧,其中包含一个名为ts
的列。
val df = Seq("20220327 021500", "20220327 031500", "20220327 011500").toDF("ts")
在spark 3.1+中,我们可以使用to_timestamp
,它会在您的情况下自动增加一个小时。
df.withColumn("time", to_timestamp($"ts", "yyyyMMdd HHmmss")).show
+---------------+-------------------+
| ts| time|
+---------------+-------------------+
|20220327 021500|2022-03-27 03:15:00|
|20220327 031500|2022-03-27 03:15:00|
|20220327 011500|2022-03-27 01:15:00|
+---------------+-------------------+
在spark 3.0和2.4.7中,我们得到了:
df.withColumn("time", to_timestamp($"ts", "yyyyMMdd HHmmss")).show
+---------------+-------------------+
| ts| time|
+---------------+-------------------+
|20220327 021500| null|
|20220327 031500|2022-03-27 03:15:00|
|20220327 011500|2022-03-27 01:15:00|
+---------------+-------------------+
但奇怪的是,在spark 2.4.7中,to_utc_timestamp
的工作方式与未来版本中的to_timestamp
相同。唯一的问题是我们不能使用自定义日期格式。然而,如果我们自己转换日期,我们可以获得:
df.withColumn("ts", concat(
substring('ts, 0, 4), lit("-"),
substring('ts, 5, 2), lit("-"),
substring('ts, 7, 5), lit(":"),
substring('ts,12,2), lit(":"),
substring('ts,14,2))
)
.withColumn("time", to_utc_timestamp('ts, "UTC"))
.show
+-------------------+-------------------+
| ts| time|
+-------------------+-------------------+
|2022-03-27 02:15:00|2022-03-27 03:15:00|
|2022-03-27 03:15:00|2022-03-27 03:15:00|
|2022-03-27 01:15:00|2022-03-27 01:15:00|
+-------------------+-------------------+
我发现了两种不同的解决方案,在这两种解决方案中,您都必须将字符串格式更改为yyyy-MM-dd HH:MM:ss:
select cast(CONCAT(SUBSTR('20220327021000',0,4),'-',
SUBSTR('20220327021000',5,2),'-',
SUBSTR('20220327021000',7,2),' ',
SUBSTR('20220327021020',9,2),':',
SUBSTR('20220327021020',11,2),':',
SUBSTR('20220327021020',13,2)) as timestamp);
select
cast(
regexp_replace("20220327031005",
'^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$','$1-$2-$3 $4:$5:$6'
) as timestamp);