---
title: "Bad Dates with DatePicker"
source: "/writing/bad-dates-with-datepicker/"
---

Article

# Bad Dates with DatePicker

Chris Fry

June 8, 2021

Photo by [Claudio Schwarz | @purzlbaum](https://unsplash.com/@purzlbaum?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/calendar?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

When using Android's [DatePicker](https://developer.android.com/reference/android/widget/DatePicker) class with a max date, the last thing you want to look at is a date that falls outside your restriction. So why is it possible for this class to display a "bad" value when in spinner mode? In order to see this, first you'll need to set the DatePicker's max date:

Then observe the resulting picker values:

Notice a bad month AND day value appear available.

Although June 8th and July 7th are not _technically_ usable, (attempting to select one of these dates jumps back to June 7, 2020) it is jarring to a user to see dates that they can't use. Luckily, there is a simple fix to ensure that these invalid dates are not displayed.

## The Problem

The root of the problem stems from the [DatePickerSpinnerDelegate](https://android.googlesource.com/platform/frameworks/base/+/77bdfb5/core/java/android/widget/DatePickerSpinnerDelegate.java) class and its `updateSpinners` method.

As you can see above, restrictions on the day and month spinners are only enforced if `mCurrentDate` is equal to `mMaxDate` or `mMinDate`. Any `mCurrentDate` value falling between `mMaxDate` and `mMinDate` will display January-December in the month spinner and all dates (depending on the month length) in the day spinner. These are all instances of the [Calendar](https://developer.android.com/reference/java/util/Calendar) class. This means that in order to strictly enforce our upper limit, `mMaxDate` and `mCurrentDate` must have the same exact value down to the MILLISECOND. `mCurrentDate`'s Calendar instance is created when DatePickerSpinnerDelegate is constructed during view creation. This makes it nearly impossible to know the time value (hour, minute, and millisecond fields) contained by `mCurrentDate` because DatePicker only allows you to set/get the day of month, month, and year fields.

## The Fix

Instead of attempting to match the time value in `mCurrentDate`, we instead will focus on eliminating time from the comparison altogether. We can do this by taking advantage of logic within the DatePickerSpinnerDelegate `setMaxDate` method.

Upon inspecting this method, we can see that if `mCurrentDate` falls after the new max date, `mCurrentDate` will be set to match `mMaxDate`. Assuming that the DatePicker has yet to be interacted with, setting a max date value of the current system date at exactly midnight guarantees that `mCurrentDate` will be after the new date.

Success! No more bad dates displayed.

But what if you want to enforce a max date that is in the future? Easy! Just use the same trick from before.

Below is the result of using the day spinner to get to June 20th starting on June 7th.

Yay! Bad dates are still gone.

This still works because as the DatePicker changes it calls DatePickerSpinnerDelegate's `setDate` method shown below:

This method will set `mCurrentDate` date back to `mMaxDate` or `mMinDate` if it falls outside the min/max restriction (which is why the bad dates aren't selectable). Therefore, when the DatePicker reaches June 20th, `mCurrentDate` is guaranteed to be after `mMaxDate` (because `mMaxDate` represents midnight of June 20th), and will be set to match `mMaxDate`.

**BE WARNED:** If you don't clear the time value from your max date restriction a user may still see bad values once they hit your max date.

Again, below is the result of using the day spinner to get to June 20th starting from June 7th. Because `mMaxDate` and `mCurrentDate` still have their original time values, they are not EXACTLY equal even though the date portion of both Calendars is aligned.

Oh no! The bad dates are back.

## In Conclusion

By removing time from the max date comparison, you'll ensure that no matter what time values `Calendar.getInstance` happens to give you it won't interfere with properly displaying your max date.

Chris ensures that only good dates are had at [Livefront](https://livefront.com/) .

-   Chris Fry

    Software Engineer

    [More from Chris](/team/chris-fry/)

    Chris Fry

### Tags

[Digital Engineering](/insights/all/?topic=digital-engineering) [Mobile Apps](/insights/all/?topic=mobile-apps)

### Share

-   Copied

## View these next.

[See all](/insights/all/?type=writing)

-   [

    Article

    How To Sabotage Your Project Using Inconsistency

    Collin Flynn

    ](/writing/how-to-sabotage-your-project-using-inconsistency/)
-   [

    Article

    Unit Testing race conditions by creating chaos (Swift)

    Sean Berry

    ](/writing/unit-testing-race-conditions-by-creating-chaos-swift/)
-   [

    Article

    UIApplicationDelegate call sequence reference

    Sean Berry

    ](/writing/uiapplicationdelegate-call-sequence-reference/)
