Python时间格式相减异常:为何出现两种不同输出?
问题分析与解决方案
首先得给你说清楚为什么会出现两种不同的输出:你的核心问题出在通过截取字符串最后8位来格式化时间差的方式完全不可靠,因为pandas的Timedelta对象转成字符串时,格式会根据时间差是否包含毫秒、时长不同而变化。
具体原因拆解
时间差的字符串格式差异
- 第一行的
Time_Start包含毫秒(16:45:04.263),和time(无毫秒)相减后,得到的Timedelta是带毫秒的,转成字符串是类似0 days 00:03:01.737000的格式。你用str(x)[-8:]截取的话,拿到的是1.737000这种毫秒相关的片段,也就是你看到的2.737000这类奇怪数值。 - 第二行的
Time_Start和time都是整秒,相减后的Timedelta没有毫秒,转成字符串是0 days 00:39:49的格式,这时候str(x)[-8:]刚好能截取到0:39:49,你手动提取出了39:49,看起来符合预期,但这完全是巧合。
- 第一行的
Python 2.x的兼容性问题
你用的是Python 2.x,后续的格式化代码要注意不能用Python 3的f-string,得用.format()语法。
修正后的完整代码
我们换一种可靠的方式:把Timedelta转换成总秒数,再手动计算分钟、秒(或小时),最后格式化成统一的字符串。
import pandas as pd # 模拟你的原始DataFrame(如果你的数据是从查询语句来的,替换成你的查询代码即可) waiting = pd.DataFrame({ 'Time_Start': ['2018-01-31 16:45:04.263', '2018-01-31 16:10:26.000'], 'CODE': ['B76', '974'], 'time': ['2018-01-31 16:48:06', '2018-01-31 16:50:06'] }) # 确保Time_Start是datetime类型(如果还没转换的话) waiting['Time_Start'] = pd.to_datetime(waiting['Time_Start']) # 转换time列为datetime类型 waiting['time'] = pd.to_datetime(waiting['time']) # 计算时间差 waiting['Duration'] = waiting['time'] - waiting['Time_Start'] # 定义格式化时间差的函数(兼容Python 2.x) def format_duration(td): total_seconds = int(td.total_seconds()) # 取整秒数,忽略毫秒 total_minutes = total_seconds // 60 seconds = total_seconds % 60 # 格式化为「分钟:秒」的形式,比如39:49 return "{:02d}:{:02d}".format(total_minutes, seconds) # 应用格式化函数 waiting['Duration'] = waiting['Duration'].apply(format_duration) print(waiting)
运行这段代码后,你会得到:
- 第一行的
Duration是03:01(对应3分1秒) - 第二行的
Duration是39:40(和你的预期39:49接近,应该是原始数据的时间差细节差异)
如果需要保留毫秒,或者显示小时,可以修改format_duration函数:
def format_duration_with_ms(td): total_seconds = td.total_seconds() hours = int(total_seconds // 3600) remaining_sec = total_seconds % 3600 minutes = int(remaining_sec // 60) seconds = remaining_sec % 60 # 格式化为「小时:分钟:秒.毫秒」 return "{:02d}:{:02d}:{:06.3f}".format(hours, minutes, seconds)
关键总结
永远不要通过截取字符串的方式处理Timedelta,因为它的字符串输出格式会随内容变化。正确的做法是基于总秒数来计算并格式化时间差,这样不管有没有毫秒、时长多久,都能得到统一的结果。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

