[Feature Request] Add date support for dcc.Slider/dcc.RangeSlider
celia-lm opened this issue · comments
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.