Android CalendarView: cannot set min date and selected date - android

I know the Android CalendarView is among the buggiest piece of software in human history, but I must use it so came here asking.
I need to open a CalendarView with:
minimum date set to today;
selected date set to today.
This is how I do it:
int day = 8;
int month = 2;
int year = 2015;
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
CalendarView calendarView = (CalendarView) findViewById(R.id.calendarView);
calendarView.setMinDate(calendar.getTimeInMillis()-2000);
calendarView.setDate(calendar.getTimeInMillis(), true, false);
fixIncredibleBugOfCalendarView(calendarView, calendar);
calendarView.setOnDateChangeListener(this);
When I run the previous code, the CalendarView:
shows the 9th of March as the first selectable day, instead of the 8th (DAY_OF_MONTH starts from 1);
shows the 15th of March as the selected date;
So I have geniously decided to include the two lines marked with *:
int day = 8;
int month = 2;
int year = 2015;
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
CalendarView calendarView = (CalendarView) findViewById(R.id.calendarView);
calendar.add(Calendar.DAY_OF_MONTH, -1); // * - subtract one day, i.e. March 7
calendarView.setMinDate(calendar.getTimeInMillis());
calendar.add(Calendar.DAY_OF_MONTH, 1); // * add one day, back to 8
calendarView.setDate(calendar.getTimeInMillis(), true, false);
fixIncredibleBugOfCalendarView(calendarView, calendar);
calendarView.setOnDateChangeListener(this);
In the first line I remove one day, in the second I add one.
With these two more lines, my CalendarView shows:
the 7th of March, as the first selectable date;
the 15th of March, as the selected date.
The method fixIncredibleBugOfCalendarView(...) should fix something (I found it on SO):
private void fixIncredibleBugOfCalendarView(CalendarView cal, Calendar date) {
// Workaround for CalendarView bug relating to setMinDate():
// https://code.google.com/p/android/issues/detail?id=42750
// Set then reset the date on the calendar so that it properly
// shows today's date. The choice of 24 months is arbitrary.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
date.add(Calendar.MONTH, 24);
cal.setDate(date.getTimeInMillis(), false, true);
date.add(Calendar.MONTH, -24);
cal.setDate(date.getTimeInMillis(), false, true);
}
}
This should not be so hard and I do not think it's a bug: it is more likely that it's my fault. Two questions: Could you please be so kind to tell me how to:
tell CalendarView the minimum date it should display?
have CalendarView showing as selected what I decide is the selected date?
Cheers

This is late, probably you have already solved the thing . But Here is my code to solve it
android.icu.util.Calendar c = android.icu.util.Calendar.getInstance();
Long min = c.getTime().getTime();
Long max = 2629746000L + c.getTime().getTime();
CalendarView cv = (CalendarView) findViewById(R.id.date_picker);
cv.setMinDate(min);
cv.setMaxDate(max);
You can also CalenderView just needs to have mindate in long format. You can also go for java
Data d = new Date();
d.getTime();
But Somehow it doesnt work because of current TimeZone.
Instead Calender returns a dateObject with respect to Current TimeZone set.

Related

How to set year limit in MaterialDatePicker dialog Android Studio

I'm having trouble set max. and min. years in Material Design Datepickerdialog, also put an image of the Material Date picker dialog box where only one year is being shown.
Below is Code
long today = MaterialDatePicker.todayInUtcMilliseconds();
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.set(Calendar.MONTH, Calendar.JANUARY);
long jan = calendar.getTimeInMillis();
calendar.setTimeInMillis(today);
int lastMonth = calendar.get(Calendar.MONTH);
calendar.set(Calendar.MONTH, lastMonth);
long dec = calendar.getTimeInMillis();
CalendarConstraints.Builder calendarConstraintBuilder = new CalendarConstraints.Builder();
calendarConstraintBuilder.setValidator(DateValidatorPointBackward.now());
calendarConstraintBuilder.setStart(jan);
calendarConstraintBuilder.setEnd(dec);
MaterialDatePicker.Builder<Long> materialBuilder = MaterialDatePicker.Builder.datePicker();
materialBuilder.setTitleText("Select Date Of Birth");
materialBuilder.setSelection(today);
materialBuilder.setCalendarConstraints(calendarConstraintBuilder.build());
final MaterialDatePicker<Long> materialDatePicker = materialBuilder.build();
inputEditTextDateOfBirth.setShowSoftInputOnFocus(false);
For other readers, note that this problem pertains to the year selection after clicking on the month-year widget.
For year range selection purposes you have a line missing:
// set minimum year variable
int minYear = 2010;
// here you set the month using the "current" calendar instance
calendar.set(Calendar.MONTH, Calendar.JANUARY);
// but you need to also set the year of "min"
calendar.set(Calendar.YEAR, minYear);
// and then get a snapshot of that time.
long jan = calendar.getTimeInMillis();
I'm not sure if that completely satisfies your requirements but at a minimum it presents a range of years. The display of text was part of my test driver using addOnPositiveButtonClickListener:
And as I was curious, this also prevents the "month selector arrows" from advancing earlier than "min":

Set minimum year (use to select DOB) for Datepicker dialog

I have create a function for my code which set a rule to restrict user to select the day earlier then systems date from date picker dialog
protected void setMinMax() {
Calendar minAllowedDate = CommUtils.getMinAllowedDate();
minAllowedDate.add(Calendar.MILLISECOND, -1000);
datePickerDialog.getDatePicker().setMinDate(minAllowedDate.getTimeInMillis());
now i want to create another date picker for user to select DOB, what i want to do is to set a rules that user DOB should be on age 4-150 which means the YEAR that user can select should be -4 & -150 from systems date. If using the the code above, what should i put in
minAllowedDate.add(Calendar.MILLISECOND, -1000);
i had tried with below code which give me the year 150 as min option
minAllowedDate.add(Calendar.YEAR, -150);
Use the below for minimum and maximum
Calendar calStart = new GregorianCalendar();
calStart.setTime(new Date());
calStart.add(Calendar.YEAR, -150);
Calendar calEnd = new GregorianCalendar();
calEnd.setTime(new Date());
calEnd.add(Calendar.YEAR, -4);
You can use android:startYear which will include the start year.
Look at the documentation here.
Found out that most of the solution using the method .add(Calendar.YEAR,-4), however this also create limit to the month & date to be select. For example, When the current date is 11/Jun/2018, running that line of code you can have 4 years before(2018-4=2014) but also limit in your month + day which you can only select date before 11/Jun/2018.
After several tried, i had came out the solution which manually set the day & month to 31/Dec so that i can have an option range from 31/12/2014 to 1/1/2014
Calendar calStart = new GregorianCalendar();
calStart.setTime(new Date());
calStart.set(Calendar.MONTH, 11);
calStart.set(Calendar.DAY_OF_MONTH, 31);
calStart.add(Calendar.YEAR, -150);
Calendar calEnd = new GregorianCalendar();
calEnd.setTime(new Date());
calEnd.set(Calendar.MONTH, 11);
calEnd.set(Calendar.DAY_OF_MONTH, 31);
calEnd.add(Calendar.YEAR,-4);
datePickerDialog.getDatePicker().setMinDate(calStart.getTimeInMillis());
datePickerDialog.getDatePicker().setMaxDate(calEnd.getTimeInMillis());

How to show a specific month in android CalendarView?

I want to show a specific month to user using android CalendarView. Please help me to implement this functionality. I wrote following code but it is not working.
CalendarView calendarView = (CalendarView) findViewById(R.id.calendarView);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(2016, 6, 1);
Calendar calendar2 = Calendar.getInstance();
calendar2.set(2016, 6, 30);
calendarView.setMinDate(calendar1.DATE);
calendarView.setMaxDate(calendar2.DATE);
Following output is coming when i am trying to run the app using above code.
Hint: What is the the value of Calendar.DATE? Documentation says 5, and so when you call this method, you are saying "5 milliseconds past Jan 01, 1970."
setMinDate(long minDate)
Sets the minimal date supported by this CalendarView in milliseconds since January 1, 1970 00:00:00 in getDefault() time zone.
Basically, that is a static field, and probably not the value that you want.
Perhaps you want getTimeInMillis() which returns the long for the value that you set the date at?
calendarView.setMinDate(calendar1.getTimeInMillis());
calendarView.setMaxDate(calendar2.getTimeInMillis());
As From my experience i always used Calender.set(Calendar.YEAR, year) method to set year and Calender.set(Calendar.MONTH, month) method to set month and Calender.set(Calendar.DAY,day) method to set day . So i am suggesting you to do same ,
String date = "1/6/2016";
String parts[] = date.split("/");
int day = Integer.parseInt(parts[0]);
int month = Integer.parseInt(parts[1]);
int year = Integer.parseInt(parts[2]);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
long milliTime = calendar.getTimeInMillis();
And now set the selected date in the calendar view by doing
mCalendarView.setDate (milliTime, true, true);

Android converting calendar in one TimeZone to local TimeZone

I am using following code to convert timezone (GMT-3) to device local timezone.
int hour=17,minute=0,day=12,month=6,year=2014;
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT-3"));
cal.set(year, (month-1), day,hour,minute);
cal.setTimeZone(TimeZone.getDefault());
Log.d("Time", cal.get(Calendar.DATE)+"/"+cal.get(Calendar.MONTH)+"/"+cal.get(Calendar.YEAR)+" , "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+" "+cal.get(Calendar.AM_PM));
My local timezone is GMT+5:30
Expected result is
Time 13/5/2014, 1:30 0
But I am getting the result
12/5/2014 , 13:30 1
Sorry for you, GregorianCalendar is sometimes the hell. Your problem is following:
If you immediately set the timezone after having set the fields for year, month etc. then this mutable calendar class will only shift the timezone retaining the already set fields containing the local time. Those fields for year, month etc. will NOT be recalculated. This behaviour causes a shift on the global timeline represented by cal.getTime(), too.
In order to force the calendar object to recalculate the fields you need to call a getter. Watch out for following code and especially remove the comment marks to see the effect.
int hour = 17, minute = 0, day = 12, month = 6, year = 2014;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
TimeZone tz1 = TimeZone.getTimeZone("GMT-3");
sdf.setTimeZone(tz1);
Calendar cal = new GregorianCalendar(tz1);
cal.set(year, (month - 1), day, hour, minute);
// System.out.println(sdf.format(cal.getTime()));
// System.out.println("Hour=" + cal.get(Calendar.HOUR_OF_DAY));
TimeZone tz2 = TimeZone.getTimeZone("GMT+0530");
sdf.setTimeZone(tz2);
cal.setTimeZone(tz2);
System.out.println(sdf.format(cal.getTime()));
System.out.println("Hour=" + cal.get(Calendar.HOUR_OF_DAY));
Output with comment-disabled lines:
2014-06-12T17:00+0530
Hour=17
Output with enabled lines after having removed the comment marks:
2014-06-12T17:00-0300
Hour=17
2014-06-13T01:30+0530
Hour=1

How to add holidays in Android Calendar?

I am trying to add a list of holidays to my calendar. I am using the Caldroid library for displaying the calendar. I want to display a list of holidays in every month for which I need to select specific dates in every month. How do I do that ? The following is what I have tried:
CODE :
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -18);
Date blueDate = cal.getTime();
cal = Calendar.getInstance();
cal.add(Calendar.DATE, 16);
int diff = cal.get(Calendar.JANUARY);
cal.add(diff, 10);
Date greenDate = cal.getTime();
I believed that diff would set the month to January and highlight the 11th of January cause I have given the value as 10 but it doesn't do so and I believe it is because I have instantiated the cal to getInstance() which would return the current month.
UPDATE :
Thanks to Meno, I have achieved the following but when I set the calendar to the second time, it takes only the updates value and does not set the first date (very obvious) but I want to know how to set multiple dates in a month without re-instantiating a new GregorianCalendar object for every month. Simply put, how do I set an array of dates in a month.
GregorianCalendar greg_cal = new GregorianCalendar();
greg_cal.set(Calendar.MONTH, Calendar.JANUARY);
greg_cal.set(Calendar.DAY_OF_MONTH, 1);
greg_cal.set(Calendar.MONTH, Calendar.JANUARY);
greg_cal.set(Calendar.DAY_OF_MONTH, 18);
Thanks in advance.
Your question does not appear to be clear. Nevertheless I try an answer. Instead of
cal = Calendar.getInstance(); // In Thailand this gives the buddhist calendar, do you want this?
cal.add(Calendar.DATE, 16); // 16 days from now, what is the intention or meaning???
cal.add(diff, 10); // first argument must be a defined constant in java.util.Calendar
I assume you just want to select a fixed date (as holiday). If so then you can call the set()-method and don't need to add days to move your calendar date forth and back:
GregorianCalendar cal = new GregorianCalendar(); // including currrent year
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 11);
Then you get as date the 11th of January in current year. By the way:
int diff = cal.get(Calendar.JANUARY);
This line is nonsense because:
Calendar.JANUARY is an int constant which is zero and denotes a value (the month) not a field. But the get(int)-method expects a field constant. The field constant with value zero corresponds to Calendar.ERA. Finally the line yields the era of cal, namely int diff = GregorianCalendar.AD = 1; assuming you use the gregorian calendar. This is surely not what you want???
UPDATED because of extra question in comment:
Reusing means that you don't create a new instance for the next calculation but reuse the same one (GregorianCalendar is mutable!). For example:
GregorianCalendar cal = new GregorianCalendar(); // including currrent year
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 11);
Date holiday1 = cal.getTime();
cal.set(Calendar.MONTH, Calendar.DECEMBER); // no new instance => reuse cal
cal.set(Calendar.DAY_OF_MONTH, 24);
Date holiday2 = cal.getTime();
...
I have also written about limiting to manipulations of month and day-of-month only because with manipulation of week-related fields the state of reused Calendar-instance depends on the order of field manipulations (very ugly and surprising).
Anyway, it is always safer to use immutable types which are available in Java 8 (not useable on Android), JodaTime and my alpha-state-library. I admit that the first contact with JodaTime can cause you feeling like lost because there are so many methods (the documentation standard is good for open-source but less good than for example in JSR-310). In your use-case I would use the type org.joda.time.LocalDate as start because you really have just a plain-date-use-case. Google and SO are your friends if you want to see more documentation beyond the original Joda documentation.
UPDATE due to extended question:
You have forgotten one important thing in your new code, namely to add the results of calendar setting to a holiday list, see here the modification:
List<Date> holidays = new ArrayList<Date>();
GregorianCalendar greg_cal = new GregorianCalendar();
greg_cal.set(Calendar.MONTH, Calendar.JANUARY);
greg_cal.set(Calendar.DAY_OF_MONTH, 1);
holidays.add(greg_cal.getTime());
greg_cal.set(Calendar.MONTH, Calendar.JANUARY);
greg_cal.set(Calendar.DAY_OF_MONTH, 18);
holidays.add(greg_cal.getTime());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for (Date d : holidays) {
System.out.println(sdf.format(d));
}
// output:
2014-01-01
2014-01-18
In an external library like JodaTime you would just use org.joda.time.LocalDate instead.
List<LocalDate> holidays = new ArrayList<LocalDate>();
LocalDate today = LocalDate.now();
holidays.add(today.withMonthOfYear(1).withDayOfMonth(1));
holidays.add(today.withMonthOfYear(1).withDayOfMonth(18));
It is pretty simple (similar in my unfinished date-and-time-library, too).

Categories

Resources