-2

In my application I have 2 arrows that show months of year 2017 and some data related to them. When the user click on ">" it should show the text February and so on. And "<" show the previous month of the current selected month as below:

< January >

This is the code I use:

on Button Next:

Calendar calendar = Calendar.getInstance();

calendar.add(Calendar.MONTH, 1);
Date nextMonth = calendar.getTime();
int yearI = calendar.get(Calendar.YEAR);
if (yearI == 2018)
    calendar.set(Calendar.YEAR,2017);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM");
String month = simpleDateFormat.format(nextMonth).toUpperCase();

monthName.setText(month);

Log.d("next month", "" + nextMonth);

on Button Next:

Calendar calendar = Calendar.getInstance();

calendar.add(Calendar.MONTH, -1);
Date prevMonth = calendar.getTime();
int yearI = calendar.get(Calendar.YEAR);
if (yearI == 2016)
    calendar.set(Calendar.YEAR,2017);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM");
String month = simpleDateFormat.format(prevMonth).toUpperCase();

monthName.setText(month);

Log.d("prev month", "" + prevMonth);

it works fine but the problem when I start with current month January and keep clicking on next till I pass Dec it goes to Jan next year which is 2018 so the data for January 2017 is not showing it only shows at first time and the same when I click on prev month it goes back from Jan 2017 to Dec 2016 instead of Dec 2017.

How can I make it show only the months of year 2017?

u_kami
  • 565
  • 12
  • 28

1 Answers1

0

The comment by njzk points out the minor problem in your logic.

Using java.time

Also, you are using troublesome old date-time classes, now legacy, supplanted by the java.time classes. Much of java.time is back-ported to Android and Java 6 and Java 7 (see below).

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

Time zone

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
int yearNumber = today.getYear();
int monthNumber = today.getMonthValue();

Year

You can maintain the state of your calendar using a type-safe Year object rather than a mere integer number. Call toString or getValue to present the value to the user.

Year year = Year.from( today );

YearMonth

Probably makes more sense to maintain the state of your calendar with the YearMonth class.

YearMonth ym = YearMonth.from( today );

Localizing

You can ask for a localized name of the month via the Month enum. To localize, specify:

  • TextStyle to determine how long or abbreviated should the string be.
  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.

Retrieve the Month object, and ask it to generate a localized String object.

Month month = today.getMonth();  // Returns an object from enum rather than a mere number.
String output = month.getDisplayName( 
    TextStyle.NARROW ,
    Locale.CANADA_FRENCH 
);

Math

The classes can do the math for you, getting next or previous month. You can call plus… or minus… methods.

LocalDate sameDateNextMonth = today.plusMonths( 1 );

Or you can use the TemporalAdjuster interface to manipulate values. Look for implementations in the TemporalAdjusters (plural name) class. Note that java.time uses immutable objects. Rather than alter (mutate) the state of an object, a new object is generated with values based on values from the original.

LocalDate firstOfNextMonth = today.with( TemporalAdjusters.firstDayOfNextMonth() );

Note how much simpler and more readable this code is than the legacy code seen in the Question.

public class CalendarWidget {
    Locale locale = Locale.getDefault() ;  // Or ask the user, such as Locale.CANADA_FRENCH.
    ZoneId zoneId = ZoneId.systemDefault() ; // Or ask the user for desired/expected zone such as `America/Montreal`.
    YearMonth displayedYearMonth = YearMonth.from( LocalDate.now( zoneId ) );  // By default, initialize to ‘today’ in a particular time zone.
…
    void moveToNextMonth() {
        // Increment the year-month.
        this.displayedYearMonth = this.displayedYearMonth.plusMonths( 1 );
        this.updateUserInterface();
    }

    void moveToPreviousMonth() {
        // Decrement the year-month.
        this.displayedYearMonth = this.displayedYearMonth.minusMonths( 1 );
        this.updateUserInterface();
    }

    void updateUserInterface() {
        // Update UI.
        String textForYearLabel = Integer.toString( this.displayedYearMonth.getYear() ) ;
        String textForMonthLabel = this.displayedYearMonth.getMonth().getDisplayName(
            TextStyle.SHORT ,
            this.locale 
        ) ;
        …
    }

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154