今天来吐槽一下 Java 的 Calendar 类的使用问题, 反正我是弄了半天.
首先是, 遇到一个问题, 输入年份和月份, 需要打印这个月的日历, 网上有不少代码, 但我用了几个感觉都不是很靠谱.
然后经过一番探索, 最后敲定了下面这个程序:
- import java.util.Arrays;
- import java.util.Calendar;
- import java.util.List;
- import java.util.Scanner;
- public class MyCal {
- public static void main(String[] args) {
- try (Scanner sc = new Scanner(System.in)) {
- System.out.println("please input the year:");
- int year = sc.nextInt();
- System.out.println("please input the month:");
- int month = sc.nextInt();
- List<String> MONTH_LIST = Arrays.asList(
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
- );
- System.out.printf("%s, M\n", MONTH_LIST.get(month - 1), year);
- System.out.println("-----------------------------");
- System.out.println("Sun Mon Tue Wed Thu Fri Sat");
- Calendar c = Calendar.getInstance();
- c.set(year, month-1, 1);
- int totalDay = c.getActualMaximum(Calendar.DATE);
- for (int i = 1; i < c.get(Calendar.DAY_OF_WEEK); i++)
- System.out.print(" ");
- for (int i = 1; i <= totalDay; i++) {
- c.set(year, month-1, i);
- System.out.printf("M", i);
- if (c.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY)
- System.out.println("");
- }
- }
- }
- }
set(year,month,date) 的问题
c.set(year, month-1, 1);
网上的代码真的不靠谱, 没几个把 API 解释清楚的.
我最后还是去翻官方 API 才发现, 第二个参数月份是从 0 开始的, 而第三个参数日期却是从 1 开始的, 着实坑了我一把.
getActualMaximum 的用法
int totalDay = c.getActualMaximum(Calendar.DATE);
getActualMaximum 方法可以直接获取 Calendar 中一个字段的最大值, getActualMaximum(Calendar.DATE) 的意思就是获取这个月日期的最大值.
还可以这样用:
getActualMaximum(Calendar.MONTH) 获取月份的最大值
getActualMaximum(Calendar.HOUR) 获取小时数的最大值
是否加 get
再说一下 c.get(Calendar.DAY_OF_WEEK) 和 Calendar.DAY_OF_WEEK 的区别, 加不加 get 有很大的区别, 我一开始也没注意, Calendar 内部实现和 get 的返回值是有偏差的, 好像是 1.
如果不注意, 可能就像我一样, 调日期的格式调了半天.
Calendar.DAY_OF_WEEK
Calendar.DAY_OF_WEEK 这个函数网上的博客很多也没讲清楚, 其实它的功能是获得当前日期是礼拜几.
但是就像上面说的一样, 如果外面不套一个 get, 实际上你获得的和 Calendar.SATURDAY 是有偏差的, 例如 Calendar.DAY_OF_WEEK==Calendar.SATURDAY 和 c.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY 是不一样的.
程序逻辑
先在循环体外面打印空格, 分析一下, 应该是填入 get(Calendar.DAY_OF_WEEK) 个 Tab(四个空格).
循环体里面的逻辑也很简单, 每次都重新设置一下日期, 从这个月的 1 号开始设置到最后一天, 如果这天正好是星期六, 那么下一次就需要换行输出.
测试
最后的结果大概是这样的:
- please input the year:
- 2019
- please input the month:
- 11
- Nov, 2019
- -----------------------------
- Sun Mon Tue Wed Thu Fri Sat
- 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
来源: http://www.bubuko.com/infodetail-3301916.html