android - Setting MinDate on DatePicker moves CalendarView to 1964 -
i'm debugging issue calendarview
in datepicker
moves october 1964 if there non-default minimum date set. reproduces @ least on api17 nexus7 emulator there reports issue on other devices platform style includes both spinners , calendar view in date picker.
here's code snippet demonstrating issue:
class datepickerdialog1964 extends datepickerdialog { datepickerdialog1964(context c) { super(c, null, 2013, 4, 21); @suppresswarnings("deprecation") date min = new date(2013-1900, 4, 21); datepicker p = getdatepicker(); p.setmindate(min.gettime()); } }
...
new datepickerdialog1964(context).show();
screen shot:
of course, expectation spinners , calendar view showing same date.
i'll keep on debugging if users have experience or other insight, please share.
related:
- issue 42750: calendarview scrolls year 1964
- using calendarview pick date in future (android-developers)
tl;dr
it's not 1964 2100 formatted badly. calendarview
has bugs. formatdaterange()
not work past 2038.
workaround #1
class datepickerdialog1964 extends datepickerdialog { datepickerdialog1964(context c) { super(c, null, 2013, 4, 21); @suppresswarnings("deprecation") date min = new date(2013-1900, 4, 21); datepicker p = getdatepicker(); calendarview cv = p.getcalendarview(); // should check null long cur = cv.getdate(); int d = cv.getfirstdayofweek(); p.setmindate(min.gettime()); cv.setdate(cur + 1000l*60*60*24*40); cv.setfirstdayofweek((d + 1) % 7); cv.setdate(cur); cv.setfirstdayofweek(d); } }
workaround #2 used
// calendar view cascade of bugs. // work around explicitly disabling it. datepicker.setcalendarviewshown(false);
analysis
calendarview
uses android.text.format.dateutils.formatdaterange()
producing month/year name in header. calendar view updates header when month number changes. example, if month number same year changes, header not updated.
somewhere during layout phase, underlying listview
invokes onscrolllistener
on calendar view if list scrolled end. if month number changed, header updated test code above, millis value passed formatdaterange()
4131043200000
somewhere in late 2100, , 2100 default maximum datepicker
.
formatdaterange()
in turn uses android.text.format.time
internal calendar representation, setting millis using set()
method. did not check underlying native code, educated guess passed in milliseconds value gets truncated 32-bit time_t
seconds value inherent year 2038 problem, wrapping value of little more 62 years. time
using struct tm
represents years int
since 1900, resulting in time
in 1960s gets formatted in header.
this can reproduced plain datepicker
calendarview
without min date set. use spinners move year 2038 or later, change month (to trigger header update) , you'll see year in header wrap 1902.
now, question remains why setting minimum date makes calendar view scroll maximum date. answer seems calendar view's week listview
adapter. indexes weeks minimum date, when minimum date changes, adapter's notifydatasetchanged()
not called. workaround #1 above works because:
- changing date more month makes month header change.
- changing first day of week makes week listview notice adapter's data has changed.
Comments
Post a Comment