Skip to content

Add date support for dcc.Slider/dcc.RangeSlider #2717

Description

@celia-lm

Describe the solution you'd like

Ideally, something like:

import datetime
from dateutil.relativedelta import relativedelta
# ...
dcc.RangeSlider(
        type='date',
        min=datetime.datetime(2020, 5, 20), 
        max=datetime.datetime(2023, 12, 20), 
        step=relativedelta(months=+6),
        value=[datetime.datetime(2022,10,20), datetime.datetime(2023,5,20)]
)

Less ideally, but understandable since dates are not json serializable (I think?):

dcc.RangeSlider(
        type='date',
        dateformat='%Y-%m-%d',
        min='2020-05-20', # str
        max='2023-12-20',
        step='0-6-0', # 6 months in string format
        # this string information would be transformed to do the calculations in the background with something like
        value=['2022-10-20', '2023-5-20']
)

Describe alternatives you've considered

from dash import Dash, html, dcc, dash_table, Input, State, Output, callback
import plotly.express as px
from dateutil.relativedelta import relativedelta
import pandas as pd
from datetime import datetime

app = Dash(__name__)

df = px.data.stocks(datetimes=True)
all_dates = df["date"]
# transform dates to string in the month/year format
all_dates_my = all_dates.apply(lambda x: x.strftime("%m/%Y")).unique()

app.layout = html.Div([
    # slider for months
    dcc.RangeSlider(
        min=0, 
        max=len(all_dates_my)-1, 
        value=[2,4],
        step=1,
        marks={
            i:{'label': all_dates_my[i]} for i in range(len(all_dates_my))
        },
        id='date-slider-01'),
    # slider for weeks
    html.Div(id='out')
])

@callback(
    Output('out', 'children'),
    Input('date-slider-01', 'value'),
    State('date-slider-01', 'marks')
)
def slider_value(val, marks):
    selected_dates_str = [marks[str(v)]['label'] for v in val]
    # selected_dates = [datetime.strptime(marks[str(v)]['label'], format="%m/%Y")  for v in val]
    filtered_df = df.query(f"date >= '{selected_dates_str[0]}' and date < '{selected_dates_str[1]}'")
    # convert the selected dates into datetime format
    selected_dates = [datetime.strptime(v, "%m/%Y")  for v in selected_dates_str]
    print(selected_dates)

    return [
        html.Div(f"the selected range is from {selected_dates_str[0]} to {selected_dates_str[1]}"),
        dash_table.DataTable(filtered_df.to_dict('records'), [{"name": i, "id": i} for i in filtered_df.columns])
    ]

if __name__ == '__main__':
    app.run(debug=True)

Additional context
Example case where this would be useful instead of using DatePicker:

The datepicker range can only move on a monthly basis and the calendar is redundant. My purpose is to specify the learning period for a machine learning model, and there is no need for calendar (day of the week) information; the key is to choose a range of 24 months.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3backlogfeaturesomething new

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions