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

如何在Dash应用中同时添加日期与时间范围选择器

解决方案:为Dash应用添加日期+时间范围选择功能

步骤1:添加时间范围选择组件

在原日期选择器的容器中,新增dcc.TimePickerRange组件,实现时间范围的选择功能:

html.Div(
    className='date-picker-container',
    children=[
        dcc.DatePickerRange(
            id='date-picker',
            start_date=df['date_time'].min().date(),
            end_date=df['date_time'].max().date(),
            min_date_allowed=df['date_time'].min().date(),
            max_date_allowed=df['date_time'].max().date(),
            initial_visible_month=df['date_time'].max().date(),
            display_format='YYYY-MM-DD',
        ),
        # 新增时间范围选择器
        dcc.TimePickerRange(
            id='time-picker',
            start_time=df['date_time'].min().time(),
            end_time=df['date_time'].max().time(),
            display_format='HH:mm:ss'
        )
    ]
)

步骤2:修改回调函数的输入与逻辑

更新回调的输入参数,加入时间选择器的返回值,同时调整日期时间的拼接与查询逻辑:

@app.callback(
    [Output('card', 'children'), Output('card1', 'children'), Output('card2', 'children')],
    [Input('table-selection', 'value'), 
     Input('date-picker', 'start_date'), 
     Input('date-picker', 'end_date'),
     Input('time-picker', 'start_time'),
     Input('time-picker', 'end_time')]
)
def update_card(table_name, start_date, end_date, start_time, end_time):
    # 校验所有必填参数
    if not table_name or not start_date or not end_date or not start_time or not end_time:
        return '', '', ''

    # 拼接日期与时间,生成完整的datetime对象
    start_datetime = datetime.strptime(f"{start_date} {start_time}", '%Y-%m-%d %H:%M:%S')
    end_datetime = datetime.strptime(f"{end_date} {end_time}", '%Y-%m-%d %H:%M:%S')

    # 构造精确到秒的查询语句
    query = f"SELECT * FROM {table_name} WHERE date_time >= '{start_datetime}' AND date_time <= '{end_datetime}'"
    cursor.execute(query)
    data = cursor.fetchall()
    df = pd.DataFrame(data, columns=[col[0] for col in cursor.description])
    
    # 原有业务逻辑(统计IGN状态切换次数)
    cycle_count = 0
    previous_state = None
    for _, row in df.iterrows():
        current_state = row["IGN"]
        if previous_state == "On" and current_state == "Off":
            cycle_count += 1
        previous_state = current_state

    cycle_count1 = 0
    previous_state1 = None
    for _, row in df.iterrows():
        current_state1 = row["IGN"]
        if previous_state1 == "Off" and current_state1 == "On":
            cycle_count1 += 1
        previous_state1 = current_state1

    # 原有业务逻辑(计算日均里程)
    df = df[(df['IGN'] == 'On') & (df['GPS'] == 'On')]
    df2 = df.drop_duplicates(subset=['Odometer'])
    df1 = df2[df2['Odometer'] != 0]
    df1["Odometer"] = df1["Odometer"].diff()
    df3 = df1.groupby(df1.date_time.dt.date)['Odometer'].sum()
    result = df3.sum() / len(df3) * 0.001 if len(df3) > 0 else 0
    formatted_num = "{:.2f}".format(result)

    # 构造三个卡片的内容
    card_content = html.Div(
        className="result-card",
        children=[
            html.H4("Average Km/day", className="card-title"),
            html.H3(formatted_num, className="card-value")
        ]
    )
    card1_content = html.Div(
        className="result-card",
        children=[
            html.H4("IGN Off Cycles", className="card-title"),
            html.H3(cycle_count, className="card-value")
        ]
    )
    card2_content = html.Div(
        className="result-card",
        children=[
            html.H4("IGN On Cycles", className="card-title"),
            html.H3(cycle_count1, className="card-value")
        ]
    )

    return card_content, card1_content, card2_content

关键细节说明

  • 默认值设置:时间选择器的初始值直接取数据集里最早/最晚记录的时间部分,确保初始状态覆盖全量数据。
  • 日期时间拼接:将日期选择器的字符串与时间选择器的字符串组合,转换为精确到秒的datetime对象,保证查询条件的准确性。
  • 查询条件优化:原逻辑中对结束日期的无意义调整(加0天)被移除,直接使用拼接后的结束时间作为查询上限,确保包含结束时刻的数据。
  • 返回值补全:原回调声明了三个输出,但仅返回一个值,这里补充了另外两个卡片的内容,避免Dash回调报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:15:00