文章目录
日期工具Date
需要先创建一个Date实例,默认保存的是系统时间,但是Date问世比较早,很多功能用起来不方便:
获取年份:+1900才是真正的公元年份,因为他是从1900开始计数的
获取月份:+1才是真正的月份,因为他是从0开始计数的
获取星期:需要修正getDay的结果,将星期天改为7,否则输出为0
获取时分秒没有需要修正的地方
Date date = new Date(); // 创建一个新的日期实例,默认保存的是系统时间
int year = date.getYear() + 1900; // 获取日期实例中的年份
System.out.println("year=" + year);
int month = date.getMonth() + 1; // 获取日期实例中的月份
System.out.println("month=" + month);
int day = date.getDate(); // 获取日期实例中的日子
System.out.println("day=" + day);
int dayWeek = date.getDay(); // 获取日期实例中的星期几
dayWeek = (dayWeek == 0) ? 7 : dayWeek; // 将星期日对应的数值改为7
System.out.println("dayWeek=" + dayWeek);
int hour = date.getHours(); // 获取日期实例中的时钟
System.out.println("hour=" + hour);
int minute = date.getMinutes(); // 获取日期实例中的分钟
System.out.println("minute=" + minute);
int second = date.getSeconds(); // 获取日期实例中的秒钟
System.out.println("second=" + second);
long time = date.getTime(); // 获取日期实例中的时间总数(单位毫秒)
System.out.println("time=" + time);
year=2021
month=7
day=13
dayWeek=2
hour=10
minute=32
second=19
time=1626143539107
日期的格式化也比较麻烦,总之代码冗余比较严重,一般不推荐这种方法!!!
日历工具Calendar
因为Date的先天不足,Java又提供了一个Calendar日历工具
与Date有几点区别说明一下:
1.创建日历实例需要用getInstance方法,而不用new关键字
2. Calendar的月份也是从0开始的,所以月份需要+1
3. Date的星期是从0开始的,但是日历的星期是从1开始计数,虽然比起Date算是进步了,但是仍然是星期天开头,星期六结尾就很难受。。。所以需要在原来的基础上把星期天变成7,其余星期-1
Calendar calendar = Calendar.getInstance(); // 创建一个日历实例
int year = calendar.get(Calendar.YEAR); // 获取日历实例中的年份
System.out.println("year=" + year);
int month = calendar.get(Calendar.MONTH) + 1; // 获取日历实例中的月份
System.out.println("month=" + month);
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); // 获取日历实例中的日子
System.out.println("dayOfMonth=" + dayOfMonth);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 获取日历实例中的星期几
dayOfWeek = dayOfWeek == 1 ? 7 : dayOfWeek - 1;
System.out.println("dayOfWeek=" + dayOfWeek);
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); // 获取日历实例中从年初开始数的日子
System.out.println("dayOfYear=" + dayOfYear);
int hour = calendar.get(Calendar.HOUR); // 获取日历实例中的时钟(12小时制)
System.out.println("hour=" + hour);
int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); // 获取日历实例中的时钟(24小时制)
System.out.println("hourOfDay=" + hourOfDay);
int minute = calendar.get(Calendar.MINUTE); // 获取日历实例中的分钟
System.out.println("minute=" + minute);
int second = calendar.get(Calendar.SECOND); // 获取日历实例中的秒钟
System.out.println("second=" + second);
int milliSecond = calendar.get(Calendar.MILLISECOND); // 获取日历实例中的毫秒
System.out.println("milliSecond=" + milliSecond);
4.Calendar提供了set方法,可以修改某个时间单位
Calendar calendar = Calendar.getInstance(); // 创建一个日历实例
// 调用带三个参数的set方法同时设置日历实例的年、月、日
calendar.set(2019, 11, 27);
// 调用带六个参数的set方法同时设置日历实例的年、月、日、时、分、秒
calendar.set(2019, 11, 27, 12, 30, 40);
System.out.println("begin set dayOfMonth="
+ calendar.get(Calendar.DAY_OF_MONTH));
// 带两个参数的set方法允许把某个时间单位改为指定数值
calendar.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("end set dayOfMonth=" + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("begin set hourOfDay=" + calendar.get(Calendar.HOUR_OF_DAY));
// 联合使用get和set方法,可对某个时间单位增减
int dayResult = calendar.get(Calendar.HOUR_OF_DAY) + 1; // 给当前日期加上一天
calendar.set(Calendar.HOUR_OF_DAY, dayResult); // 设置日历实例中的日期
System.out.println("end set hourOfDay="
+ calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("begin set minute=" + calendar.get(Calendar.MINUTE));
// 调用add方法,直接在当前时间的基础上增加若干数值
calendar.add(Calendar.MINUTE, 10); // 给当前时间加上10分钟
System.out.println("end add minute=" + calendar.get(Calendar.MINUTE));
5.Calendar类型与date类型互相转换
// 把Calendar类型的数据转换为Date类型
private static void convertCalendarToDate() {
Calendar calendar = Calendar.getInstance(); // 创建一个日历实例
Date date = calendar.getTime(); // 调用日历实例的getTime方法,获得日期信息
System.out.println("日历转日期 date=" + date.toString() + ", calendar=" + calendar.toString());
}
// 把Date类型的数据转换为Calendar类型
private static void convertDateToCalendar() {
Calendar calendar = Calendar.getInstance(); // 创建一个日历实例
Date date = new Date(); // 创建一个日期实例
calendar.setTime(date); // 调用日历实例的setTime方法,设置日期信息
System.out.println("日期转日历 date=" + date.toString() + ", calendar=" + calendar.toString());
}
6.如何计算日历时间的天数?
private static void countDays() {
Calendar calendarA = Calendar.getInstance(); // 创建一个日历实例
calendarA.set(2019, 3, 15); // 设置第一个日历实例的年月日
Calendar calendarB = Calendar.getInstance(); // 创建一个日历实例
calendarB.set(2019, 9, 15); // 设置第二个日历实例的年月日
long timeOfA = calendarA.getTimeInMillis(); // 获得第一个日历实例包含的时间总数(单位毫秒)
long timeOfB = calendarB.getTimeInMillis(); // 获得第二个日历实例包含的时间总数(单位毫秒)
// 先计算二者的差额,再把毫秒计量的差额转换为天数
long dayCount = (timeOfB - timeOfA) / (1000 * 60 * 60 * 24);
System.out.println("dayCount=" + dayCount);
}
7.如何打印当前月份的月历?
// 打印当前月份的月历
private static void printMonthCalendar() {
Calendar calendar = Calendar.getInstance(); // 创建一个日历实例
calendar.set(Calendar.DATE, 1); // 设置日期为当月1号
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); // 获得该日期对应的星期几
dayOfWeek = dayOfWeek == 1 ? 7 : dayOfWeek - 1;
int lastDay = calendar.getActualMaximum(Calendar.DATE); // 获取当月的最后一天
// 拼接月历开头的年月
String yearAndMonth = String.format("\n%21s%d年%d月", "",
calendar.get(calendar.YEAR), calendar.get(calendar.MONTH) + 1);
System.out.println(yearAndMonth);
System.out.println(" 星期一 星期二 星期三 星期四 星期五 星期六 星期日");
for (int i = 1; i < dayOfWeek; i++) { // 先补齐1号前面的空白
System.out.printf("%7s", "");
}
for (int i = 1; i <= lastDay; i++) { // 循环打印从一号到本月最后一天的日子
String today = String.format("%7d", i);
System.out.print(today);
if ((dayOfWeek + i - 1) % 7 == 0) { // 如果当天是星期日,末尾就另起一行
System.out.println();
}
}
}
Java8本地日期时间工具
先天不良的Date和后来的Calendar在开发中都存在一定的通病:
1.获取当前月份的时候都是从0开始
2.日历获取星期的时候也是从星期天开始算起的
3.日历获取的最小单位是毫秒,精度不够高,不适合一些科学计算场合
4.日历没有提供判断闰年的方法
5.日历缺乏格式化工具
本地日期类型LocalDate
实例化调用now方法
LocalDate date = LocalDate.now(); // 获得本地日期的实例
System.out.println("date=" + date.toString());
int year = date.getYear(); // 获得该日期所在的年份
System.out.println("year=" + year);
// 获得该日期所在的月份。注意getMonthValue返回的是数字月份,getMonth返回的是英文月份
int month = date.getMonthValue();
System.out.println("month=" + month + ", english month=" + date.getMonth());
int dayOfMonth = date.getDayOfMonth(); // 获得该日期所在的日子
System.out.println("dayOfMonth=" + dayOfMonth);
int dayOfYear = date.getDayOfYear(); // 获得该日期在一年当中的序号
System.out.println("dayOfYear=" + dayOfYear);
// 获得该日期是星期几。注意getDayOfWeek返回的是英文,后面的getValue才返回数字星期几
int dayOfWeek = date.getDayOfWeek().getValue();
System.out.println("dayOfWeek=" + dayOfWeek + ", english weekday=" + date.getDayOfWeek());
int lengthOfYear = date.lengthOfYear(); // 获得该日期所在的年份一共有多少天
System.out.println("lengthOfYear=" + lengthOfYear);
int lengthOfMonth = date.lengthOfMonth(); // 获得该日期所在的月份一共有多少天
System.out.println("lengthOfMonth=" + lengthOfMonth);
boolean isLeapYear = date.isLeapYear(); // 判断该日期所在的年份是否为闰年
System.out.println("isLeapYear=" + isLeapYear);
date=2021-07-13
year=2021
month=7, english month=JULY
dayOfMonth=13
dayOfYear=194
dayOfWeek=2, english weekday=TUESDAY
lengthOfYear=365
lengthOfMonth=31
isLeapYear=false
本地时间类型LocalTime
通过本地类型Localtime可以获取本地时间的,也用now方法进行实例化,甚至可以通过getNano方法获得秒钟之后的纳秒单位,代码如下:
LocalTime time = LocalTime.now(); // 获得本地时间的实例
System.out.println("time=" + time.toString());
int hour = time.getHour(); // 获得该时间所在的时钟
System.out.println("hour=" + hour);
int minute = time.getMinute(); // 获得该时间所在的分钟
System.out.println("minute=" + minute);
int second = time.getSecond(); // 获得该时间所在的秒钟
System.out.println("second=" + second);
// 一秒等于一千毫秒,一毫秒等于一千微秒,一微秒等于一千纳秒,算下来一秒等于十亿纳秒
int nano = time.getNano(); // 获得该时间秒钟后面的纳秒单位
System.out.println("nano=" + nano);
本地日期时间类型LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("当前日期时间为:" + localDateTime.toString());
当前日期时间为:2021-07-13T14:42:00.520269
实战练习
利用本地日期实现万年历
引用本地日期工具localDate
引入二维数组保存当月的各个星期分布,第一维表示5个星期,第二维表示每个星期的7天
public static void main(String[] args) {
showCalendar(2020, 2); // 根据指定年月显示当月的月历
}
// 根据指定年月显示当月的月历
public static void showCalendar(int year, int month) {
// 行分隔标记
String line = "\n ————————————————————————————————————————————————————————————————\n";
String slit = " | "; // 列分隔标记
String[] weekTitles = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
LocalDate date = LocalDate.of(year, month, 1); // 获取当月1日的本地日期实例
// 拼接当前日历的年月标题(包含年份、月份、是否闰年、当月天数等信息)
String calendar = String.format("\n%20s%d年(%s)%d月(共%d天)%s",
"", date.getYear(), date.isLeapYear() ? "闰年" : "平年",
date.getMonthValue(), date.lengthOfMonth(), line);
String weekTitle = slit; // 月份的星期标题
// 拼接星期一到星期日的周标题
for (int i = 0; i < weekTitles.length; i++) {
weekTitle = String.format("%s%3s%s", weekTitle, weekTitles[i], slit);
}
int firstWeekNum = date.getDayOfWeek().getValue(); // 当月第一天是星期几
int[][] weekdays = new int[5][7]; // 星期的二维数组,每月横跨五个星期
loop : for (int i = 0; i < 5; i++) { // 遍历组装各个星期
for (int j = 0; j < 7; j++) { // 通过循环填满星期数组
if (i==0 && j < firstWeekNum-1) { // 当前日期还是上个月份的日子
continue; // 不处理,继续下个日期
} else { // 当前日期位于本月份
weekdays[i][j] = date.getDayOfMonth(); // 给星期数组填写本月的日期
if (date.getDayOfMonth() == date.lengthOfMonth()) { // 如果是本月的最后一天
break loop; // 跳出外层的遍历循环
} else {
date = date.plusDays(1); // 日期加一
}
}
}
}
String weekDetail = ""; // 月份的星期详情
for (int i = 0; i < 5; i++) { // 遍历星期的二维数组,把各星期以及分隔串拼接起来
weekDetail = String.format("%s%s%s", weekDetail, line, slit);
for (int j = 0; j < 7; j++) { // 拼接本星期的内容,每个日子占据六位空间,且靠右对齐
if (weekdays[i][j] > 0) { // 属于本月的日期,则填写具体日期
weekDetail = String.format("%s%6d%s", weekDetail, weekdays[i][j], slit);
} else { // 不属本月的日期,则留空
weekDetail = String.format("%s%6s%s", weekDetail, "", slit);
}
}
}
calendar = String.format("%s%s%s%s", calendar, weekTitle, weekDetail, line);
System.out.println(calendar); // 打印拼接好的万年历日期
}