How to use Return range Values from date_input to filter dataframe

Hi team. Can somone please share an example of how to use the return values from date_input, when Range paramaters are used?

For example:

date = st.sidebar.date_input(

     "Select Confirmation Date Range",

    (datetime.date(2019, 7, 6),datetime.date(2020,7,6)))

st.write(date)

Returns:

(datetime.date(2019, 7, 6),datetime.date(2020,7,6)

assuming the default dates are what I select.

How do I isolate each date into a variable so I can use it to filter a dataframe?

thanx much!!

Hey @Joe_Pawlowski,

I used the min_value and max_value parameters from the documentation on date_input and i mocked up this example that returns one date from the date_input:

import streamlit as st
import datetime

st.title("Date range")

min_date = datetime.datetime(2020,1,1)
max_date = datetime.date(2022,1,1)

a_date = st.date_input("Pick a date", min_value=min_date, max_value=max_date)

##this uses streamlit 'magic'!!!! 
"The date selected:", a_date

This produces ‘a_date’ of a single value between the two dates specified (Jan 1, 2020 and Jan, 1, 2022):
date_range_ex · Streamlit

Happy Streamlit-ing!
Marisa

hey @Joe_Pawlowski,

So it’s getting late here and apparently I can’t read anymore! :woman_facepalming: :see_no_evil: :speak_no_evil: How embarrassing!!!

I fixed my example to show you how to isolate a single date from a returned tuple of dates when your trying to get a range of dates from date_input ( :dizzy_face:)

import streamlit as st
import datetime

st.title("Date range")

min_date = datetime.datetime(2020,1,1)
max_date = datetime.date(2022,1,1)

a_date = st.date_input("Pick a date", (min_date, max_date))

##this uses streamlit 'magic'!!!!
"The date selected:", a_date
"The type", type(a_date)
"Singling out a date for dataframe filtering", a_date[0]

here is a gif of how that works:
date_range_ex · Streamlit

2 Likes

Ahh. Smarty pants.

Thanks much.

Go home, get some rest.

:wink:

1 Like

Thanks nice idea

1 Like

Hey @Marisa_Smith,

this demo is simple and works.
Unfortunately the date_input loses its focus after I select the first date and then closes the selection window. Do you have any ideas where this might come from?

My code itself is quite big (~1,6k lines), with several functions prior and afterwards, thus it is not really practicable to share it here
I crunched it down to only have auth and this date_input as filtering option (the rest is skipped) and I think it has to do with my login process, since the password is checked to equal a hashed password in a file, and this happens on every run (if it does not match the user is logged off).

But nontheless in a single setup with only the date_input, the code afterwards is still beeing executed, even though no second date is selected :face_with_raised_eyebrow:

Is this the desired behaviour of this widget?? :thinking:

E.g. in your example if you’d try to access a_date[1] in a line like this:

st.write(“this will result in an error after the first date is selected”, a_date[1])

The code will run into an error


import streamlit as st
import datetime

ss = st.session_state

base = datetime.date(2022,7,1)
## reading from pandas dataframe thus datetime objects
dates = [base + datetime.timedelta(days=x) for x in range(5)]

def updateDateRange():
    if 'dateRange' in ss and isinstance(ss.dateRange, tuple) and len(ss.dateRange)==2:
        ### do some kind of magic for later use ###
        ss.filter = {}
        ## convertion to string due to saving in json later on as default values
        ss["filter"]['dateRange'] = (ss.dateRange[0].strftime("%d/%m/%Y"), ss.dateRange[1].strftime("%d/%m/%Y"))

a_date = st.date_input(
    label="Select date range",
    value=(dates[0], dates[-1]),
    min_value=dates[0],
    max_value=datetime.date.today(),
    key="dateRange",
    on_change=updateDateRange,
)

st.write("This is a test (shown whenever)", a_date[0])

if len(ss.dateRange)==2:
    st.write("This i b test :P (only shown if start and end date are selected)", a_date[1])

st.write("this will result in an error after the first date is selected", a_date[1])

@Marisa_Smith
Strangely I can ommit this behaviour if I have an output (st.write(
)) in der “on_change” function


The code below will run by itself with or without the st.write, but represents exactly what I call in the larger project, but in my original code this won’t work, unless I have the st.write(‘###’)
weired and I completely do not understand why


import streamlit as st
import datetime

ss = st.session_state

ss.analysis = {"filter": {}}

def updateDateRange():
    if 'dateRange' in ss and isinstance(ss.dateRange, tuple) and len(ss.dateRange)==2:
        st.write("##############")    # <-- with this it works, as it is supposed to be....but why?
        ss["analysis"]["filter"]['dateRange'] = (ss.dateRange[0].strftime("%d/%m/%Y"), ss.dateRange[1].strftime("%d/%m/%Y"))

base = datetime.date(2022,7,1)
## reading from pandas dataframe thus datetime objects
dates = [base + datetime.timedelta(days=x) for x in range(5)]

if "dateRange" not in ss:
    ss.defaultDateRange = (dates[0], dates[-1])

st.date_input(
    label="Select date range",
    value=ss.defaultDateRange,
    min_value=dates[0],
    max_value=datetime.date.today(),
    key="dateRange",
    on_change=updateDateRange,
)

if isinstance(ss.dateRange, tuple) and len(ss.dateRange)==2 and "dateRange" not in ss["analysis"]["filter"]:
    ss["analysis"]["filter"]["dateRange"] = (ss.dateRange[0].strftime("%d/%m/%Y"), ss.dateRange[1].strftime("%d/%m/%Y"))

after some more debugging I now think, that this results from too much calculating time when some functions are called prior or after the date_input which for example get a table from a DB and do some manipulation on dataframes etc. I reduced the number of function calls a lot (~10 left over) and now the date_input with the range works most of the time but not always :face_with_spiral_eyes:

Is it possible to lock streamlit until a second date is selected or the user manually clicks on the backround of the app to indicate that only one date is needed and thus the endDate will be the startDate :question:

1 Like