确定该月的第一天是星期几,并存储从该位置开始的日期编号
Determine what day of the week the first of that month falls on and store the day numbers starting at that position
我正在尝试用其中的日期填充一个数组,
比如这个月八月,应该显示
Sunday Monday Tuesday Wednesday ... Saturday
null 1 2 3 ... 6
... ... ... ... ... ...
它正在处理这个:
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);
}
}
}
但如果我决定将月份更改为 2016 年 1 月,那就错了。
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
null null null null null 5 6
... ... ... ... ... ... ...
5 假设为 1。
你们会如何改变这一切?
因为无聊,所以决定写一个完整的class,但略有不同。
我没有为天数创建 String[48]
数组,而是为一个月中的几周创建了一个 int[weeks][7]
二维数组,其中 weeks
在 4
和6
,取决于当月的天数,以及当月第一天的工作日。 0
的值是 "blank" 天。
代码已增强为 Locale
感知,即确定一周是从星期日(例如美国)还是星期一(例如欧洲大部分地区)开始。
我还添加了一个很好的 print()
方法,它将在给定的 Locale
中打印月份,并自动调整输出大小。
核心输入是 YearMonth
标识月份,以及 Locale
。与您的代码类似的基本逻辑是这 7 行:
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;
如你所见,for
循环使用了 2 个迭代器变量,一个用于二维数组中的位置 (weekDay
),一个用于要分配的天数 (dayOfMonth
).
这就是我处理您似乎遇到的问题的方式。
这里是完整的 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);
}
}
测试
CalendarMonth.of(2016, Month.AUGUST).print();
CalendarMonth.of(2016, Month.JANUARY).print();
CalendarMonth.of(2016, Month.JANUARY, Locale.FRANCE).print();
输出
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
如您所见,它调整为从星期一开始的一周,这恰好将周数从 6 减少到 5。
我正在尝试用其中的日期填充一个数组,
比如这个月八月,应该显示
Sunday Monday Tuesday Wednesday ... Saturday
null 1 2 3 ... 6
... ... ... ... ... ...
它正在处理这个:
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);
}
}
}
但如果我决定将月份更改为 2016 年 1 月,那就错了。
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
null null null null null 5 6
... ... ... ... ... ... ...
5 假设为 1。 你们会如何改变这一切?
因为无聊,所以决定写一个完整的class,但略有不同。
我没有为天数创建 String[48]
数组,而是为一个月中的几周创建了一个 int[weeks][7]
二维数组,其中 weeks
在 4
和6
,取决于当月的天数,以及当月第一天的工作日。 0
的值是 "blank" 天。
代码已增强为 Locale
感知,即确定一周是从星期日(例如美国)还是星期一(例如欧洲大部分地区)开始。
我还添加了一个很好的 print()
方法,它将在给定的 Locale
中打印月份,并自动调整输出大小。
核心输入是 YearMonth
标识月份,以及 Locale
。与您的代码类似的基本逻辑是这 7 行:
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;
如你所见,for
循环使用了 2 个迭代器变量,一个用于二维数组中的位置 (weekDay
),一个用于要分配的天数 (dayOfMonth
).
这就是我处理您似乎遇到的问题的方式。
这里是完整的 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);
}
}
测试
CalendarMonth.of(2016, Month.AUGUST).print();
CalendarMonth.of(2016, Month.JANUARY).print();
CalendarMonth.of(2016, Month.JANUARY, Locale.FRANCE).print();
输出
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
如您所见,它调整为从星期一开始的一周,这恰好将周数从 6 减少到 5。