Why Calendar.SEPTEMBER is not working?

264 views Asked by At

I want to see a month which contains whole days.

private void createRandomData(InMemoryCursor cursor) {
    List<Object[]> data = new ArrayList<>();
    Calendar today = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
    today.set(Calendar.HOUR_OF_DAY,0);
    today.set(Calendar.MINUTE, 0);
    today.set(Calendar.SECOND, 0);
    today.set(Calendar.MILLISECOND, 0);
    mStart = (Calendar) today.clone();
    mStart.add(Calendar.SEPTEMBER, -5);
    while (mStart.compareTo(today) <= 0) {
        data.add(createItem(mStart.getTimeInMillis()));
        mStart.add(Calendar.SEPTEMBER, 1);
    }
    cursor.addAll(data);
}

When I write Calendar.SEPTEMBER(or other months), I see red line on Calendar.SEPTEMBER which contains:

Must be one of: Calendar.ERA, Calendar.YEAR, Calendar.MONTH, Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH, Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND, Calendar.ZONE_OFFSET, Calendar.DST_OFFSET less... (Ctrl+F1) This inspection looks at Android API calls that have been annotated with various support annotations (such as RequiresPermission or UiThread) and flags any calls that are not using the API correctly as specified by the annotations. Examples of errors flagged by this inspection: Passing the wrong type of resource integer (such as R.string) to an API that expects a different type (such as R.dimen). Forgetting to invoke the overridden method (via super) in methods that require it Calling a method that requires a permission without having declared that permission in the manifest Passing a resource color reference to a method which expects an RGB integer value. ...and many more. For more information, see the documentation at developer.android.com/tools/debugging/annotations.html

When I run it despite the red line, It shows complicated dates like: see

I use this library from GitHub:https://github.com/jruesga/timeline-chart-view Is problem related to library? or It is about Java calendar?

2

There are 2 answers

0
Michael Dodd On

You are using an incompatible option. The first parameter of Calendar.add() is a Unit of Time (Day, Week, Hour etc) as defined by the possible options outlined in the error. Calendar.SEPTEMBER is not a unit of time, it is a convenience constant representing the MONTH of September that is typically used in the set() method instead.

Assuming you're iterating through months, you'll need Calendar.MONTH instead.

0
AudioBubble On

As explained in @Michael's answer, you can't use Calendar.SEPTEMBER in the add method.

If you want to add or subtract a specified number of months, just use Calendar.MONTH. If you want to add/subtract days, you use Calendar.DAY_OF_MONTH and so on.

The Calendar API might be confusing sometimes (most times, IMO), and has lots of problems and design issues.

In Android, there's a better alternative: you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).

As you're getting a Calendar in the default timezone, a good candidate for replacement is a org.threeten.bp.ZonedDateTime (it represents a date and time in a specific timezone). First I use the now() method (that takes the current date/time at the JVM default timezone). Then I use a org.threeten.bp.LocalTime to set the time to midnight.

I also use the minusMonths method to get a date 5 months before the current date, and inside the loop I use the toInstant() method, to get the millis value, and the plusMonths method to get the next month:

// get today at default timezone, at midnight
ZonedDateTime today = ZonedDateTime.now().with(LocalTime.MIDNIGHT);
// 5 months ago
ZonedDateTime start = today.minusMonths(5);
while (start.compareTo(today) <= 0) {
    data.add(createItem(start.toInstant().toEpochMilli()));
    start = start.plusMonths(1);
}

If you want to add/subtract minutes instead of months, for example, you can use the methods minusMinutes and plusMinutes. There are other methods for another units as well (such as hours, days, and so on), check the javadoc to see all the options.


The problem of using the default timezone is that it can be changed without notice, even at runtime, so it's better to always make it explicit which one you're using.

With Calendar, you can use TimeZone.getTimeZone(zoneName):

Calendar todayCal = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"), Locale.getDefault());

And with ThreeTen Backport, you can use ZoneId.of(zoneName):

ZonedDateTime today = ZonedDateTime.now(ZoneId.of("Europe/London")).with(LocalTime.MIDNIGHT);

In the example above, I used Europe/London, but you can change it to any timezone you want. The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin). Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.

You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds() or TimeZone.getAvailableIDs().