justanoob
justanoob

Reputation: 1807

For loop increment value when iterating through days of week

In my Android app i'm using the following Map to map the days of the Calendar class to Strings:

Map<Integer, String> map = new HashMap<>(7);
                                             // values of the Calendar field
map.put(Calendar.MONDAY, "Mon");             // 2
map.put(Calendar.TUESDAY, "Tue");            // 3
map.put(Calendar.WEDNESDAY, "Wed");          // 4
map.put(Calendar.THURSDAY, "Thu");           // 5
map.put(Calendar.FRIDAY, "Fri");             // 6
map.put(Calendar.SATURDAY, "Sat");           // 7
map.put(Calendar.SUNDAY, "Sun");             // 1

And adding Buttons dynamically to a LinearLayout with the day text like this:

LinearLayout dayLayout = (LinearLayout) findViewById(R.id.layout_days);

for(int i = 1; i <= 7; i++) {
    Button button = new Button(this);
    button.setText(map.get(i));
    dayLayout.addView(button);
}

This works fine, but the list of Buttons always start from Sunday regardless of the current Locale.

I'm trying to rewrite this loop so it takes the first day of the week into account.

Something like this:

LinearLayout dayLayout = (LinearLayout) findViewById(R.id.layout_days);
int firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();

for(int i = firstDayOfWeek; i <= 7; ???) { // this is where i'm stuck
    Button button = new Button(this);
    button.setText(map.get(i));
    dayLayout.addView(button);
}

The problem is i cannot figure out the correct formula for fetching the days in the correct order.

If the first day of the week is Monday, the loop has to go as 2 3 4 5 6 7 1.

I guess i have to play with the modulo operator, i just don't know how.

I'd really appreciate any advice, maybe my approach is completely wrong.

Upvotes: 3

Views: 2242

Answers (6)

janos
janos

Reputation: 124704

First of all, you should not use the numeric values of the Calendar.* constants. The numeric values are implementation detail, not API, and should not be used directly like the for-loop tries.

It will be better to store the constants in a list:

List<Integer> days = Arrays.asList(
    Calendar.MONDAY,
    Calendar.TUESDAY,
    Calendar.WEDNESDAY,
    Calendar.TUESDAY,
    Calendar.FRIDAY,
    Calendar.SATURDAY,
    Calendar.SUNDAY
    );

And then find the index whose value corresponds to firstDayOfWeek:

int start = days.indexOf(firstDayOfWeek);

And then, create the correct map key by rotating the 0..6 indexes by the value of start and the modulo operator, like this:

for(int i = 0; i < 7; i++) {
  int key = days.get((start + i) % 7);
  Button button = new Button(this);
  button.setText(map.get(key));
  dayLayout.addView(button);
}

Upvotes: 2

RobCo
RobCo

Reputation: 6495

Here is a complete example that also removes the need for the Map so that weekdays are displayed in correct locale.

DateFormatSymbols symbols = new DateFormatSymbols(Locale.getDefault());
// Array with 8 elements (first is empty string), so Calendar constants correspond to the day.
String[] dayNames = symbols.getShortWeekdays();

int firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();
int daysStart = Calendar.SUNDAY;
int daysEnd = Calendar.SATURDAY;
int dayCount = (daysEnd - daysStart) + 1; // +1 because both ends inclusive

for(int i = 0; i < dayCount; i++) {

    int day = firstDayOfWeek + i;
    if(day > daysEnd) // loop back if over the end
        day -= dayCount;

    Button button = new Button(this);
    button.setText(dayNames[day]);
    dayLayout.addView(button);
}

Day starts at firstDayOfWeek: 2 3 4 5 6 7 1
English: Mon Tue Wed Thu Fri Sat Sun
Japanese: 月 火 水 木 金 土 日

Upvotes: 0

Diego Torres Milano
Diego Torres Milano

Reputation: 69318

Isn't this what you want?

Map<String, Integer> names = (new GregorianCalendar()).getDisplayNames(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.ENGLISH);

which gives

Tue, 3
Thu, 5
Sun, 1
Sat, 7
Wed, 4
Mon, 2
Fri, 6

Upvotes: 0

hqt
hqt

Reputation: 30284

Define an array like this:

int[] daysInWeek = [2, 3, 4, 5, 6, 7, 1]

Then solution should be:

// define day of week you want to print out first.
int firstDayOfWeekIndex = 0;  // print Monday first
for (int i = 0; i < 7; i++) {
  int currentDay = (firstDayOfWeekIndex + i) % 7;
  String day = map.get(daysInWeek[currentDay]);

  // print this day to your button
  Button button = new Button(this);
  button.setText(day);
  dayLayout.addView(button);
}

Upvotes: 0

Shawnzey
Shawnzey

Reputation: 196

maybe add a count into the for loop and compare count to 7, so that the loop will go through all 7 days regardless of the start.

so maybe something like this

LinearLayout dayLayout = (LinearLayout) findViewById(R.id.layout_days);
int firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();
int count = 1;

for(int i = firstDayOfWeek; count <= 7; i++) {

count++    
if(i <= 7)
    firstDayOfWeek = 1;

Button button = new Button(this);
button.setText(map.get(i));
dayLayout.addView(button);
}

Upvotes: 0

Joe C
Joe C

Reputation: 15704

Starting with an i as 1 2 3 4 5 6 7,
you can take these mod 7, giving 1 2 3 4 5 6 0
and then add 1: giving 2 3 4 5 6 7 1.

Upvotes: 0

Related Questions