Datepicker, get years between 2 user inputs

I have 2 datepickers (one for start date and one for end date). I would like to be able to get a list of all years between what the user selects.

So for example, if the user chooses 2022 as a start year and 2030 as an end year, I would like to return a list of all years from 2022 until 2030. So in this case, I want html.H1 to return the list. Can you please advise?

Code below:

dcc.DatePickerSingle(id="lease_start_date",
                                             initial_visible_month=date.today(),
                                             placeholder="MM/DD/YYYY",
                                             style={"margin-left": "20px", "font-size": 13}),


 dcc.DatePickerSingle(id="lease_end_date",
                         initial_visible_month=date.today(),
                         placeholder="MM/DD/YYYY",
                         style={"margin-left": "20px", "font-size": 13}),

html.H1(id="test")

@app.callback(
    Output("test", "children"),
    [Input("lease_start_date", "value"),
     Input("lease_end_date", "value")]
)
def get_years(year1, year2):
    return [y for y in range(year1.year, year2.year + 1)]

Hi,

Two things I noticed:

  1. dcc.DatePicker has no “value” prop, it should be “date” instead. So Input("lease_start_date", "date") and the same for the second picker.

  2. The date prop is a string , so you should transform it to a date. Using datetimethis would be:

@app.callback(
    Output("test", "children"),
    [Input("lease_start_date", "date"),
     Input("lease_end_date", "date")]
)
def get_years(date1, date2):
    if (date1 is not None) and (date2 is not None):
        year1 = dt.datetime.fromisoformat(date1).year
        year2 = dt.datetime.fromisoformat(date2).year
        return [y for y in range(year1, year2 + 1)]
    else:
        raise PreventUpdate

If you return a list to html.H1, it will most likely be concatenated to a single string. So it is better to replace it by a div and return a list of html.H1 instead

1 Like

Thank you! Works great!

I tried to get the output in the form of a table using your code above, I just amended it to look like:

def get_years(date1, date2):
    if (date1 is not None) and (date2 is not None):
        year1 = dt.datetime.fromisoformat(date1).year
        year2 = dt.datetime.fromisoformat(date2).year
        fig = go.Figure(data=[go.Table(
            header=dict(
                values=[[''], ['<b>TOTAL CASH FLOW</b>'], [y for y in range(year1, year2+1)]],
                line_color='darkslategray',
                align=['left', 'center'],
                font=dict(color='white', size=12)
            ),

I am getting this result if the user chooses 2025 and 2028. Is there a way I can make the years not stacked on top of each other but instead be side-by-side?

I am not that familiar with go.Table, but my bet is that is happening because you are passing a list of lists in the values key…

Does spreading them fix the issue?

values=["", '<b>TOTAL CASH FLOW</b>', *[y for y in range(year1, year2+1)]]
1 Like

works perfectly, thank you! much appreciated !