如何在Polars中计算两列时间的时间差?(跨午夜场景)
在Polars中计算跨午夜的时间差(小时)
我需要计算字符串格式的开始时间与结束时间之间的时长(以小时为单位),难点在于处理跨午夜的情况(比如23:00到24:00)。Polars原生不支持解析24:00这种时间格式,我自己写了一套处理逻辑,但感觉太复杂,想找更简洁的实现方式。
我的原始实现代码:
import polars as pl df = pl.DataFrame( { 'start_time': [ '23:00', '00:00' ], 'end_time': [ '24:00', '01:00' ] } ) ( df .with_columns( start_time = pl.col('start_time').str.to_time('%H:%M'), end_time = pl.col('end_time').replace('24:00', '00:00').str.to_time('%H:%M') ) .with_columns( duration = ( pl.when(pl.col('end_time') == pl.time(0, 0, 0)) .then(86400000000000) .otherwise(pl.col('end_time').cast(pl.Int64)) - pl.col('start_time').cast(pl.Int64)) / 3600000000000 ) )
更简洁的两种实现方式
方法1:转成当日分钟数计算
直接将时间字符串转成当日的总分钟数,处理跨午夜时只需给结束时间加1440分钟(24小时),逻辑直观易懂:
import polars as pl df = pl.DataFrame( { 'start_time': ['23:00', '00:00'], 'end_time': ['24:00', '01:00'] } ) result = df.with_columns( # 拆分时间字符串,转成当日总分钟数 start_minutes=pl.col('start_time').str.split(':').map_elements( lambda x: int(x[0])*60 + int(x[1]), return_dtype=pl.Int32 ), end_minutes=pl.col('end_time').str.split(':').map_elements( lambda x: int(x[0])*60 + int(x[1]), return_dtype=pl.Int32 ) ).with_columns( # 跨午夜判断:结束分钟数小于开始则加1440分钟,再算差值转小时 duration_hours=( pl.when(pl.col('end_minutes') < pl.col('start_minutes')) .then(pl.col('end_minutes') + 1440 - pl.col('start_minutes')) .otherwise(pl.col('end_minutes') - pl.col('start_minutes')) ) / 60 ).drop('start_minutes', 'end_minutes') print(result)
方法2:利用Datetime类型处理
通过给时间绑定日期,将24:00直接转成次日的00:00,再利用Polars的时间差计算功能,代码更贴合时间处理逻辑:
import polars as pl df = pl.DataFrame( { 'start_time': ['23:00', '00:00'], 'end_time': ['24:00', '01:00'] } ) result = df.with_columns( # 将开始时间转成当日datetime start_dt=pl.col('start_time').str.to_datetime('%H:%M'), # 处理24:00:转成00:00后加1天,其他时间保持当日 end_dt=( pl.col('end_time').str.replace('24:00', '00:00').str.to_datetime('%H:%M') + pl.when(pl.col('end_time') == '24:00').then(pl.duration(days=1)).otherwise(pl.duration(days=0)) ) ).with_columns( # 计算时间差并转成小时 duration_hours=(pl.col('end_dt') - pl.col('start_dt')).dt.total_hours() ).drop('start_dt', 'end_dt') print(result)
两种方法都能得到预期结果:
shape: (2, 3) ┌────────────┬──────────┬──────────────┐ │ start_time ┆ end_time ┆ duration_hours │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ f64 │ ╞════════════╪══════════╪══════════════╡ │ 23:00 ┆ 24:00 ┆ 1.0 │ │ 00:00 ┆ 01:00 ┆ 1.0 │ └────────────┴──────────┴──────────────┘
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

