Spark Scala 时间戳过滤:筛选晚9点至11点的记录
解决Spark Scala过滤时间戳(仅保留21:00-23:00记录)的问题
我来帮你分析下问题所在,然后给出可行的解决思路和代码:
问题根源
你当前的代码之所以没得到预期结果,主要有两个核心问题:
- 字符串比较的逻辑错误:你用
hh:mm:ss(12小时制)生成了pickupWindow字段,比如晚上9点会变成09:09:29。当你用字符串和"9:00:00"比较时,字符串是按字典序判断的——"09..."的第一个字符是0,比"9..."的9小,所以"09:09:29" < "9:00:00",导致符合条件的第一条记录被错误过滤。 - 冗余的PM判断:虽然你加了
where($"tpep_pickup_datetime".contains("PM")),但结合上面的字符串比较错误,还是没法正确筛选目标时间范围。
两种正确的解决方法
方法1:直接提取24小时制小时数(推荐,更高效)
利用Spark的hour()函数直接提取时间戳的小时数(24小时制),然后过滤21到23之间的记录,这样完全不用处理字符串比较的问题:
import org.apache.spark.sql.functions.{to_timestamp, hour, col} // 先将字符串转成Timestamp类型,再提取小时过滤 val filteredDF = stamp .withColumn("pickup_timestamp", to_timestamp(col("tpep_pickup_datetime"), "MM/dd/yyyy hh:mm:ss a")) .filter(hour(col("pickup_timestamp")) >= 21 && hour(col("pickup_timestamp")) <= 23) .select("tpep_pickup_datetime", "tpep_dropoff_datetime", "total_amount") // 按需选择字段 filteredDF.show(false)
方法2:用24小时制字符串比较
如果一定要保留时间字符串字段,把格式改成HH:mm:ss(24小时制),这样字符串的字典序和时间顺序一致,比较逻辑就正确了:
import org.apache.spark.sql.functions.{to_timestamp, date_format, col} val filteredDF = stamp .withColumn("pickupWindow", date_format(to_timestamp(col("tpep_pickup_datetime"), "MM/dd/yyyy hh:mm:ss a"), "HH:mm:ss")) .filter(col("pickupWindow") >= "21:00:00" && col("pickupWindow") <= "23:00:00") .select("tpep_pickup_datetime", "tpep_dropoff_datetime", "total_amount", "pickupWindow") filteredDF.show(false)
验证结果
用你的输入数据测试的话,两种方法都会返回以下正确结果:
+----------------------+----------------------+----------+ |tpep_pickup_datetime |tpep_dropoff_datetime |total_amount| +----------------------+----------------------+----------+ |05/18/2018 09:09:29 PM|05/18/2018 09:52:53 PM|42.8 | |05/18/2018 11:00:00 PM|05/18/2018 11:09:13 PM|23.5 | +----------------------+----------------------+----------+
内容的提问来源于stack exchange,提问作者peakstatus
相关产品推荐
相关产品推荐

