Repository: streamlit/streamlit

Issue:
Unecessary warning for date_input widget with default value rewritten by session state api
### Checklist

- [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.
- [X] I added a very descriptive title to this issue.
- [X] I have provided sufficient information below to help reproduce this issue.

### Summary

I have a date_input with min, max, default value and a key for a session_state variable as well. And because of that, the streamlit is showing an annoying warning message saying that the default value was rewritten by the session_state variable.

But when I remove the default value so only the key value from session_state is used, I got an error because by default streamlit sets the value as the current date, in which is greater than the max_value I setup in the input.

So I tried in many ways to suppress this warning but I could make it. The only way I've heard was by commenting some lines of code in the streamlit source code. But I don't want to in that way for obvious reasons.

Another person had the same problem as me [in this discussion on streamlit community](https://discuss.streamlit.io/t/why-do-default-values-cause-a-session-state-warning/15485/13). Then I came here to see if anyone had already made an issue for that.

### Reproducible Code Example

[![Open in Streamlit Cloud](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://issues.streamlitapp.com/?issue=gh-6167)

```Python
import streamlit as st
import datetime

min_date = datetime.date(2020,1,1)
max_date = datetime.date(2020,12,31)

if 'custom_date' not in st.session_state:
  st.session_state['custom_date'] = min_date

st.date_input('Date:', min_value=min_date, max_value=max_date, value=min_date, key='custom_date')

st.write(st.session_state['custom_date'])
```


### Steps To Reproduce

1. Create a streamlit page with the code snippet above
2. And only for the first time you open it, will show the annoying warning
3. If you remove the default value in the date_input for the warning to not show again, it will give an error as the default date will be set the current date, in which is after the max_value.

### Expected Behavior

I expected that this warning didn't show off, or even have an option on streamlit to suppress it.

### Current Behavior

The warning message:

![Screenshot from 2023-02-22 09-59-19](https://user-images.githubusercontent.com/95307858/220627491-fec590b5-c8ff-4ebb-a1e9-355be3ff916e.png)

The error message when you remove the default value:

![Screenshot from 2023-02-22 09-57-58](https://user-images.githubusercontent.com/95307858/220627599-7cfd891e-c87c-43db-b9f5-3d49bc9df164.png)


### Is this a regression?

- [ ] Yes, this used to work in a previous version.

### Debug info

- Streamlit version: Streamlit, version 1.18.1
- Python version: Python 3.10.6
- Operating System: Linux Pop_OS
- Browser: Firefox
- Virtual environment: None


### Additional Information

I know that in this simple example I don't even need a session state variable. I could just set a variable for the date_input and then get the data from it. But I have a real example on my work in which I NEED to use a session state variable.

### Are you willing to submit a PR?

- [ ] Yes, I am willing to submit a PR!


Discussion:
Hey @eduardochaves1 👋 

Here's how you can workaround the issue. Use one session state variable to hold the default value (e.g. "custom_date"), and another to assign as the widget key (e.g. "date_key"). If the widget key doesn't exist in session state, assign the default value to the former variable:

```python
import datetime
import streamlit as st

min_date = datetime.date(2020, 1, 1)
max_date = datetime.date(2020, 12, 31)

if "date_key" not in st.session_state:
    st.session_state["custom_date"] = min_date

st.date_input(
    "Date:",
    min_value=min_date,
    max_value=max_date,
    value=st.session_state["custom_date"],
    key="date_key",
)

st.write(st.session_state["date_key"])
```

![image](https://user-images.githubusercontent.com/20672874/220635140-91511da5-f4e1-42d3-a23f-38b8059bad5c.png)

Yes, it solves the warning problem, but then I have another problem that I should've said before on this issue (my bad).

In the real project I'm working on, I have a reset date button like that:

```python
import streamlit as st
import datetime

min_date = datetime.date(2020,1,1)
max_date = datetime.date(2020,12,31)

if 'date_key' not in st.session_state:
  st.session_state['custom_date'] = min_date

st.date_input('Date:', min_value=min_date, max_value=max_date, value=st.session_state['custom_date'], key='date_key')

if st.button('Reset Date', type='primary'):
  st.session_state['date_key'] = min_date

st.write(st.session_state['date_key'])
```

And when I try to reset the date with the session state key, this error shows up:

![Screenshot from 2023-02-22 11-05-57](https://user-images.githubusercontent.com/95307858/220644941-613e39e9-8419-4db7-b5a5-5e786dfac13d.png)

This looks to me like a validation issue. If a key is provided, the value in that key should be used for validation instead of a default value defined by streamlit. This should just work:

```python
import streamlit as st
import datetime

min_date = datetime.date(2020,1,1)
max_date = datetime.date(2020,12,31)

if 'custom_date' not in st.session_state:
    st.session_state['custom_date'] = min_date

st.date_input('Date', min_value=min_date, max_value=max_date, key='custom_date')
```

Did you paste the right code on that message? Because it doesn't have the reset button I said I was using on my project. And it gives the same error I was talking before that the default value date_input sets (if not specified) is the device current date, in which 2023 is greater than the max_date which is 2020
I think I didn't make myself clear enough. "This should just work" was intended to mean "it doesn't actually work and I consider that to be a bug". I think your step 3 in the **Steps To Reproduce** section of your report is the right thing to do in this case, and if it worked (which it doesn't) I wouldn't care about the warning in step 2.

Ow yea, I'd say it needs some modification, cause in my mind it should get the default value from the key when `value` not declared, or maybe set up some conditionals for instead of using the current date, use the min or max value **when** they're declared in the function call
I had a meeting with my boss and we decided to remove the default value AND the max_value as well, so then the warning doesn't show anymore and it doesn't give an error for the current date been greater than the max_value. The downside is that the user can now selects a date till 2031, but for me is better than having a warning. For now was the best option for us.
@eduardochaves1 Thanks for reporting this issue. I agree that this scenario that should somehow work 👍  But to fix this, it's probably not as easy as just removing the warning message since there is a reason why the warning is there as well

Resolving patch:
diff --git a/lib/streamlit/elements/widgets/time_widgets.py b/lib/streamlit/elements/widgets/time_widgets.py
--- a/lib/streamlit/elements/widgets/time_widgets.py
+++ b/lib/streamlit/elements/widgets/time_widgets.py
@@ -21,6 +21,7 @@
     TYPE_CHECKING,
     Any,
     Final,
+    List,
     Literal,
     Sequence,
     Tuple,
@@ -78,7 +79,6 @@ def _parse_date_value(
     if value == "today":
         parsed_dates = [datetime.now().date()]
     elif value == "default_value_today":
-        # Set value default.
         parsed_dates = [datetime.now().date()]
     elif isinstance(value, datetime):
         parsed_dates = [value.date()]
@@ -158,17 +158,27 @@ def from_raw_values(
         max_value: SingleDateValue,
     ) -> _DateInputValues:
         parsed_value, is_range = _parse_date_value(value=value)
+        parsed_min = _parse_min_date(
+            min_value=min_value,
+            parsed_dates=parsed_value,
+        )
+        parsed_max = _parse_max_date(
+            max_value=max_value,
+            parsed_dates=parsed_value,
+        )
+
+        if value == "default_value_today":
+            v = cast(List[date], parsed_value)[0]
+            if v < parsed_min:
+                parsed_value = [parsed_min]
+            if v > parsed_max:
+                parsed_value = [parsed_max]
+
         return cls(
             value=parsed_value,
             is_range=is_range,
-            min=_parse_min_date(
-                min_value=min_value,
-                parsed_dates=parsed_value,
-            ),
-            max=_parse_max_date(
-                max_value=max_value,
-                parsed_dates=parsed_value,
-            ),
+            min=parsed_min,
+            max=parsed_max,
         )
 
     def __post_init__(self) -> None:


Test patch:
diff --git a/lib/tests/streamlit/elements/date_input_test.py b/lib/tests/streamlit/elements/date_input_test.py
--- a/lib/tests/streamlit/elements/date_input_test.py
+++ b/lib/tests/streamlit/elements/date_input_test.py
@@ -171,6 +171,20 @@ def test_value_out_of_range(self, value, min_date, max_date):
     def test_value_in_range(self, value, min_date, max_date):
         st.date_input("the label", value=value, min_value=min_date, max_value=max_date)
 
+    def test_default_min_if_today_is_before_min(self):
+        min_date = date(9998, 2, 28)
+        st.date_input("the label", min_value=min_date, max_value=date(9999, 2, 28))
+
+        c = self.get_delta_from_queue().new_element.date_input
+        assert datetime.strptime(c.default[0], "%Y/%m/%d").date() == min_date
+
+    def test_default_max_if_today_is_after_min(self):
+        max_date = date(1001, 2, 28)
+        st.date_input("the label", min_value=date(1000, 2, 28), max_value=max_date)
+
+        c = self.get_delta_from_queue().new_element.date_input
+        assert datetime.strptime(c.default[0], "%Y/%m/%d").date() == max_date
+
     def test_range_session_state(self):
         """Test a range set by session state."""
         date_range_input = [date(2024, 1, 15), date(2024, 1, 15) + timedelta(2)]