I am trying to populate an array with the date in there,
For example, this month August, it should show
Sunday Monday Tuesday Wednesday ... Saturday
null 1 2 3 ... 6
... ... ... ... ... ...
It is working with this:
import java.time.LocalDate;
import java.util.Scanner;
public class buildCalendar {
String[] calendar = new String[48];
private final int firstDayOfMonth = 1;
Scanner sc = new Scanner(System.in);
int month, year;
public buildCalendar() {
System.out.println("Month: ");
month = sc.nextInt();
sc.nextLine();
System.out.println("Year: ");
year = sc.nextInt();
newCalendar(month, year);
}
public void newCalendar(int month, int year) {
LocalDate inputDate = LocalDate.of(year, month, firstDayOfMonth);
int dayOfWeek = inputDate.withDayOfMonth(firstDayOfMonth).getDayOfWeek().getValue();
// populate String array
int i = 0;
while (i <= calendar.length) {
if (i == dayOfWeek) {
for (int j = 0; j < inputDate.lengthOfMonth(); j++) {
calendar[i] = Integer.toString(i);
i++;
}
}
i++;
}
for (String string : calendar) {
System.out.println(string);
}
}
}
But if I decide to change the month to January 2016, it will be wrong.
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
null null null null null 5 6
... ... ... ... ... ... ...
5 is suppose to be 1. How would you guys change this around?
Because I was bored, I decided to write a full class for this, but slightly different.
Instead of a String[48]
array for the day numbers, I create an int[weeks][7]
2D array for the weeks of the month, where weeks
is between 4
and 6
, depending on the number of days in the month, and the weekday of the first day of the month. A value of 0
is the "blank" day.
The code has been enhanced to be Locale
aware, i.e. to determine whether a week starts on Sunday (e.g. US) or Monday (e.g. most of Europe).
I also adding a nice print()
method, which will print the month in the given Locale
, with automatic sizing of the output.
The core input is a YearMonth
identifying the month, and a Locale
. The base logic similar to your code is these 7 lines:
this.firstWeekdayOfWeek = WeekFields.of(this.locale).getFirstDayOfWeek();
DayOfWeek firstWeekdayOfMonth = this.yearMonth.atDay(1).getDayOfWeek();
int startWeekDay = (firstWeekdayOfMonth.getValue() - this.firstWeekdayOfWeek.getValue() + 7) % 7;
int endWeekDay = startWeekDay + this.yearMonth.lengthOfMonth();
this.weekdays = new int[(endWeekDay + 6) / 7][7];
for (int weekDay = startWeekDay, dayOfMonth = 1; weekDay < endWeekDay; weekDay++, dayOfMonth++)
this.weekdays[weekDay / 7][weekDay % 7] = dayOfMonth;
As you can see, the for
loop uses 2 iterator variables, one for the position in the 2D array (weekDay
), and one for the day number to be assigned (dayOfMonth
).
This is how I handled the problem you seem to have.
Here is the full class:
public final class CalendarMonth implements Comparable<CalendarMonth> {
private final YearMonth yearMonth;
private final Locale locale;
private final DayOfWeek firstWeekdayOfWeek;
private final int[][] weekdays;
public static CalendarMonth of(int year, int month) {
return new CalendarMonth(YearMonth.of(year, month), Locale.getDefault());
}
public static CalendarMonth of(int year, int month, Locale locale) {
Objects.requireNonNull(locale, "locale");
return new CalendarMonth(YearMonth.of(year, month), locale);
}
public static CalendarMonth of(int year, Month month) {
return new CalendarMonth(YearMonth.of(year, month), Locale.getDefault());
}
public static CalendarMonth of(int year, Month month, Locale locale) {
Objects.requireNonNull(locale, "locale");
return new CalendarMonth(YearMonth.of(year, month), locale);
}
public static CalendarMonth of(YearMonth yearMonth) {
Objects.requireNonNull(yearMonth, "yearMonth");
return new CalendarMonth(yearMonth, Locale.getDefault());
}
public static CalendarMonth of(YearMonth yearMonth, Locale locale) {
Objects.requireNonNull(yearMonth, "yearMonth");
Objects.requireNonNull(locale, "locale");
return new CalendarMonth(yearMonth, locale);
}
private CalendarMonth(YearMonth yearMonth, Locale locale) {
this.yearMonth = yearMonth;
this.locale = locale;
// Build weekdays array
this.firstWeekdayOfWeek = WeekFields.of(this.locale).getFirstDayOfWeek();
DayOfWeek firstWeekdayOfMonth = this.yearMonth.atDay(1).getDayOfWeek();
int startWeekDay = (firstWeekdayOfMonth.getValue() - this.firstWeekdayOfWeek.getValue() + 7) % 7;
int endWeekDay = startWeekDay + this.yearMonth.lengthOfMonth();
this.weekdays = new int[(endWeekDay + 6) / 7][7];
for (int weekDay = startWeekDay, dayOfMonth = 1; weekDay < endWeekDay; weekDay++, dayOfMonth++)
this.weekdays[weekDay / 7][weekDay % 7] = dayOfMonth;
}
public void print() {
// Get day names and determine width of longest name
String[] dayName = new String[7];
for (int i = 0; i < 7; i++)
dayName[i] = this.firstWeekdayOfWeek.plus(i).getDisplayName(TextStyle.FULL, this.locale);
int width = Arrays.stream(dayName).mapToInt(String::length).max().getAsInt();
// Print month name
String title = this.yearMonth.format(DateTimeFormatter.ofPattern("MMMM uuuu", this.locale));
System.out.println(rightTrim(center(title, width * 7 + 6)));
// Print day names
StringBuilder line = new StringBuilder();
for (int i = 0; i < 7; i++)
line.append(center(dayName[i], width)).append(' ');
System.out.println(rightTrim(line.toString()));
// Print day numbers
for (int[] week : this.weekdays) {
line.setLength(0);
for (int i = 0; i < 7; i++)
line.append(center((week[i] == 0 ? "" : String.format("%2d", week[i])), width)).append(' ');
System.out.println(rightTrim(line.toString()));
}
}
private static String center(String text, int width) {
if (text.length() >= width)
return text;
char[] buf = new char[width];
Arrays.fill(buf, ' ');
System.arraycopy(text.toCharArray(), 0, buf, (width - text.length() + 1) / 2, text.length());
return new String(buf);
}
private static String rightTrim(String text) {
return text.replaceFirst("\\s+$", "");
}
@Override
public String toString() {
return this.yearMonth.toString();
}
@Override
public int compareTo(CalendarMonth that) {
int cmp = this.yearMonth.compareTo(that.yearMonth);
if (cmp == 0)
cmp = this.locale.toLanguageTag().compareTo(that.locale.toLanguageTag());
return cmp;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof CalendarMonth) {
CalendarMonth other = (CalendarMonth) obj;
return (this.yearMonth.equals(other.yearMonth) &&
this.locale.equals(other.locale));
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(this.yearMonth, this.locale);
}
}
Test
CalendarMonth.of(2016, Month.AUGUST).print();
CalendarMonth.of(2016, Month.JANUARY).print();
CalendarMonth.of(2016, Month.JANUARY, Locale.FRANCE).print();
Output
August 2016
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
January 2016
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
janvier 2016
lundi mardi mercredi jeudi vendredi samedi dimanche
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
As you can see, it adjusts to a week starting on Monday, which happens to reduce the number of weeks from 6 to 5.