You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python datetime时间范围判断与限时区域车辆停车时长计算技术问询

解决Python中Datetime时间范围判断与受限区域停车时长计算问题

嘿,我来帮你搞定这两个核心问题——其实用你已经在使用的pandas加上Python自带的datetime模块就完全能解决,不需要额外安装工具库,下面一步步拆解方案:

一、判断Datetime是否处于指定时间范围内

不管是单个时间对象,还是pandas DataFrame里的批量时间列,都有简洁的处理方式:

1. 单个Datetime对象的判断

直接用比较运算符就行,注意要保证所有时间的时区一致(如果有时区的话):

from datetime import datetime

target_dt = datetime(2024, 5, 20, 14, 30)
start_range = datetime(2024, 5, 20, 8, 0)
end_range = datetime(2024, 5, 20, 18, 0)

# 判断是否在范围内
is_in_range = start_range <= target_dt <= end_range
print(is_in_range)  # 输出True

2. Pandas DataFrame批量判断

先确保你的时间列已经转成pandas的datetime类型(如果还没转的话),然后用布尔索引或者between()方法:

import pandas as pd

# 示例数据
df = pd.DataFrame({
    'park_start': ['2024-05-20 07:30', '2024-05-20 15:00', '2024-05-20 19:00'],
    'park_end': ['2024-05-20 09:00', '2024-05-20 17:00', '2024-05-20 21:00']
})

# 转成datetime类型
df['park_start'] = pd.to_datetime(df['park_start'])
df['park_end'] = pd.to_datetime(df['park_end'])

# 定义限制时间范围
restriction_start = pd.to_datetime('2024-05-20 08:00')
restriction_end = pd.to_datetime('2024-05-20 18:00')

# 批量判断停车开始时间是否在限制范围内
df['start_in_restriction'] = df['park_start'].between(restriction_start, restriction_end)
# 或者用布尔表达式更灵活
df['end_in_restriction'] = (df['park_end'] >= restriction_start) & (df['park_end'] <= restriction_end)

二、计算受限区域内的停车时长

这部分是核心场景,我们需要计算停车时间段和区域强制限制时间段的重叠时长。假设你有两个CSV:

  • 一个是车辆停车记录(包含车辆ID、停车区域ID、停车开始/结束时间)
  • 另一个是区域限制规则(包含区域ID、限制开始/结束时间,可能是单日或周期性规则)

1. 基础场景:单日限制规则的重叠计算

先把两个DataFrame按区域ID关联,然后用矢量化方法计算重叠时长(比apply()效率高很多):

import pandas as pd
from datetime import timedelta

# 模拟停车记录CSV数据
park_records = pd.DataFrame({
    'car_id': ['A1', 'A2', 'A3'],
    'zone_id': ['Z01', 'Z01', 'Z02'],
    'park_start': pd.to_datetime(['2024-05-20 07:30', '2024-05-20 16:00', '2024-05-20 10:00']),
    'park_end': pd.to_datetime(['2024-05-20 09:00', '2024-05-20 19:00', '2024-05-20 12:00'])
})

# 模拟区域限制规则CSV数据
zone_restrictions = pd.DataFrame({
    'zone_id': ['Z01', 'Z02'],
    'restrict_start': pd.to_datetime(['2024-05-20 08:00', '2024-05-20 09:00']),
    'restrict_end': pd.to_datetime(['2024-05-20 18:00', '2024-05-20 17:00'])
})

# 关联两个DataFrame
merged_df = pd.merge(park_records, zone_restrictions, on='zone_id', how='left')

# 计算重叠时间段的起止时间
merged_df['overlap_start'] = merged_df[['park_start', 'restrict_start']].max(axis=1)
merged_df['overlap_end'] = merged_df[['park_end', 'restrict_end']].min(axis=1)

# 计算重叠时长,没有重叠的情况设为0
merged_df['restricted_park_duration'] = merged_df['overlap_end'] - merged_df['overlap_start']
merged_df['restricted_park_duration'] = merged_df['restricted_park_duration'].where(
    merged_df['overlap_start'] < merged_df['overlap_end'], 
    timedelta(0)
)

# 可以转成小时数更直观
merged_df['restricted_hours'] = merged_df['restricted_park_duration'].dt.total_seconds() / 3600

2. 进阶场景:周期性限制规则(如每周固定时段)

如果限制是每周重复的(比如周一到周五的8:00-18:00),需要把停车时间段拆分成单日片段,再逐个和当日的限制时间计算重叠:

def split_park_period(row):
    # 把停车时间段拆分成每天的时间段
    dates = pd.date_range(row['park_start'].date(), row['park_end'].date(), freq='D')
    periods = []
    for date in dates:
        day_start = datetime.combine(date, datetime.min.time())
        day_end = datetime.combine(date, datetime.max.time())
        period_start = max(row['park_start'], day_start)
        period_end = min(row['park_end'], day_end)
        periods.append({'car_id': row['car_id'], 'zone_id': row['zone_id'], 
                        'period_start': period_start, 'period_end': period_end})
    return pd.DataFrame(periods)

# 拆分所有停车记录为单日片段
split_df = park_records.apply(split_park_period, axis=1).explode().reset_index(drop=True)

# 这里假设区域限制是每周一到周五8:00-18:00,先判断日期是否在工作日
split_df['is_weekday'] = split_df['period_start'].dt.weekday < 5
# 设置当日的限制时间
split_df['restrict_start'] = split_df['period_start'].dt.floor('D') + pd.Timedelta(hours=8)
split_df['restrict_end'] = split_df['period_start'].dt.floor('D') + pd.Timedelta(hours=18)

# 只计算工作日的重叠时长
split_df['overlap_start'] = split_df[['period_start', 'restrict_start']].max(axis=1)
split_df['overlap_end'] = split_df[['period_end', 'restrict_end']].min(axis=1)
split_df['daily_restricted'] = split_df['overlap_end'] - split_df['overlap_start']
split_df['daily_restricted'] = split_df['daily_restricted'].where(
    (split_df['is_weekday']) & (split_df['overlap_start'] < split_df['overlap_end']),
    timedelta(0)
)

# 按车辆ID汇总总受限时长
total_restricted = split_df.groupby('car_id')['daily_restricted'].sum()

几点实用建议

  • 先统一时间格式:确保所有时间列都用pd.to_datetime()转换,检查时区(如果涉及跨时区),用dt.tz_localize()或dt.tz_convert()统一时区。
  • 优先矢量化操作:避免用apply()处理大数据量,矢量化方法的效率会高几十倍。
  • 处理缺失值:关联后如果有缺失的限制规则,要考虑默认逻辑(比如无限制则时长为0)。

内容的提问来源于stack exchange,提问作者Michael McKeever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:14:20