Java GregorianCalendar and Calendar misplace weeke

2019-03-06 13:15发布

问题:

I'm trying to use either Calendar or Gregorian Calendar to iterate and create a date grid. However, both of them seem to think that August, 2010 has 30 days, and that September 2 and 3 are weekends. It's as if the calendar has the wrong year, but I've tripple-checked that parameter. Here are some excerpts.

startDate.set(2010, 8, 28);

SchedulerCalendar currentDate = (SchedulerCalendar) startDate.clone(); 
  for(int i = 0; i<daysDisplayed; i++){ 
   newDate = new TextView(this); 
   String dateString = currentDate.get(Calendar.MONTH)+"/"+currentDate.get(Calendar.DATE);
   //+"/"+currentDate.get(Calendar.YEAR);
   newDate.setText(dateString);
   newDate.setId(i+1);
   newDate.setWidth(blockWidth);
   newDate.setHeight(DATE_HEIGHT);
   dateBar.addView(newDate);
   currentDate.add(Calendar.DATE, 1);
  }


 private class SchedulerCalendar extends GregorianCalendar {
  @Override
  public void add(int field, int value) {
   super.add(field, value);
   if(this.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY) {
    if(value>=0) super.add(Calendar.DATE, 2);
    if(value<0) super.add(Calendar.DATE, -1);
   }
   if(this.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY) {
    if(value>=0) super.add(Calendar.DATE, 1);
    if(value<0) super.add(Calendar.DATE, -2);
   }
  }
 }

回答1:

I strongly suspect you're not taking into account the fact that the month is 0-based. So this:

startDate.set(2010, 8, 28);

is setting it to September 28th 2010. You haven't said what you expect it to be, but I suspect you wanted August (which is month 7 in java.util.Calendar).

I suspect this is the problem, given that October 2nd and 3rd are Saturday and Sunday.

Can I strongly recommend that you use Joda Time as your date and time API instead of java.util.{Date,Calendar}? The built-in classes have lots of gotchas like this.



回答2:

If you want to continue to use java.util.Calendar, you should probably also use the Calendar.JANUARY, Calendar.FEBRUARY, etc. constants.



回答3:

As others have already mentioned it might be some of the common "off by one" errors this library design helps to make. The Java API is more or less some wrapping of a UNIX timestamp largely inspired by some C library.

You should at least use the appropriate Enumerations to improve readability and make sure to not pass Date/Calendar objects to other methods which could work with some immutable representation (String, Long, ...) of the data depending on the use case.

If you are heavily involved with Times, Dates and Calendars you should consider using JodaTime and look into JSR 310, the Date and Time API which might appear in a future Java release.