前面介绍了日历工具Calendar的基本用法,乍看起来Calendar与Date两个半斤八两,似乎没有多大区别,那又何苦庸人自扰鼓捣一个新玩意呢?显然这样小瞧了Calendar,其实它的作用大着呢,接下来不妨深入探讨一下Calendar的几种实际应用,主要包括:Calendar和Date类型互相转换、计算两个日历时间的天数、打印当前月份的月历等,分别说明如下。

1、Calendar和Date类型互相转换
虽说Date早就应该被Calendar取代,但毕竟是前辈,而且Java也一直没有抛弃它,特别有一点:Date拥有搭配的日期格式化工具SimpleDateFormat,可以很方便地输出指定格式的日期时间字符串,敢问Calendar有此绝活么?既然Calendar无法覆盖Date的所有功能,那就必须支持互相转换Calendar和Date类型,从而让日期实例去执行日历实例所不能完成的任务。因为类型转换的要求是Calendar提出来的,所以这个转换动作理应由它实现,这里用到了Calendar的getTime方法和setTime方法,其中getTime方法的返回值就是Date类型的实例,而setTime方法可将Date实例填入Calendar实例。下面是通过getTime和setTime方法转换日期类型和日历类型的代码例子:

	// 把Calendar类型的数据转换为Date类型
private static void convertCalendarToDate() {
// 创建一个日历实例
Calendar calendar = Calendar.getInstance();
// 调用日历实例的getTime方法,获得日期信息
Date date = calendar.getTime();
System.out.println("convertCalendarToDate date=" + date.toString() + ", calendar=" + calendar.toString());
} // 把Date类型的数据转换为Calendar类型
private static void convertDateToCalendar() {
// 创建一个日历实例
Calendar calendar = Calendar.getInstance();
// 创建一个日期实例
Date date = new Date();
// 调用日历实例的setTime方法,设置日期信息
calendar.setTime(date);
System.out.println("convertDateToCalendar date=" + date.toString() + ", calendar=" + calendar.toString());
}

  

2、计算两个日历时间的天数
根据两个给定的时间,计算二者间隔的天数,这个业务场景也很常见。例如为了安全起见,网站每隔若干天就要求用户重新登录;又如信用卡还款,银行需要在还款日之前多少天提醒用户等等。这时用到了Calendar的getTimeInMillis方法,该方法可返回毫秒计量的时间总数,只要把两个日历实例的时间总数相减,再把二者的差额从毫秒单位换算成以天为单位,即可求得这两个日历时间之间的天数。据此编写的计算方法代码如下所示:

	// 计算两个日历实例间隔的天数
private static void countDays() {
Calendar calendarA = Calendar.getInstance();
// 设置第一个日历实例的年月日
calendarA.set(2018, 3, 15);
Calendar calendarB = Calendar.getInstance();
// 设置第二个日历实例的年月日
calendarB.set(2018, 9, 15);
// 获得第一个日历实例包含的时间总数(单位毫秒)
long timeOfA = calendarA.getTimeInMillis();
// 获得第二个日历实例包含的时间总数(单位毫秒)
long timeOfB = calendarB.getTimeInMillis();
// 先计算二者的差额,再把毫秒计量的差额转换为天数
long dayCount = (timeOfB-timeOfA)/(1000*60*60*24);
System.out.println("dayCount="+dayCount);
}

  

3、打印当前月份的月历
对于期待周末的学生和上班族来说,一份安排妥当的月历是必不可少的,现在利用Calendar功能便能制作一个简单的月历。月历的每行均为一个星期,行首是星期一,行尾是星期日,然后分行打印当月从1号到月末的所有日子。其中的年、月、星期都是明确的,唯有月末的日子是变化着的,比如1、3、5、7、8、10、12这七个月的月末是31号,4、6、9、11这四个月的月末是30号,2月每逢闰年有29天、其它年份则有28天。倘若为了确定当月的最后一天,就得自己编码判断这些繁复的细节,可谓是绞尽脑汁、伤筋动骨。所幸Calendar早已提供了getActualMaximum方法,该方法用于获得指定时间单位的最大合法值,如果指定的时间单位是Calendar.DATE,则该方法的返回值就为当月的最后一天。于是获取月末日子的代码仅需下列一行而已:

		// 获取当月的最后一天
int lastDay = calendar.getActualMaximum(Calendar.DATE);

这下月历具备的所有要素都集齐了,包括当前年份、当前月份、当月1号、当月最后一天,再把中间的日子分星期依次排列,一个简洁朴素的月历便出炉了。下面是使用日历工具计算并打印当前月历的代码例子:

	// 打印当前月份的月历
private static void printMonthCalendar() {
// 创建一个日历实例
Calendar calendar = Calendar.getInstance();
// 设置日期为当月1号
calendar.set(Calendar.DATE, 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 %d年%d月",
calendar.get(calendar.YEAR), calendar.get(calendar.MONTH)+1);
System.out.println(yearAndMonth);
System.out.println(" 星期一 星期二 星期三 星期四 星期五 星期六 星期日");
// 先补齐1号前面的空白
for (int i=1; i<dayOfWeek; i++) {
System.out.print(" ");
}
// 循环打印从一号到本月最后一天的日子
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();
}
}
}

运行上述的月历代码,观察到的打印结果如下图所示。

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(四十二)日历工具的常见应用的更多相关文章

  1. Java开发笔记(十二)布尔变量论道与或非

    在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...

  2. 网站开发进阶(四十二)巧用clear:both

    网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...

  3. Java开发笔记(一百二十四)AWT绘图操作

    前面介绍了如何使用画笔在控件上展示图像,可是图像来源于磁盘图片,无法即兴绘制个性化的图案.所幸画笔工具Graphics不仅能够描绘图像,还支持绘制常见的几何形状,也支持绘制文本字符串,除了绘制图像用到 ...

  4. Java开发笔记(一百二十五)AWT图像加工

    前面介绍了如何使用画笔工具Graphics绘制各种图案,然而Graphics并不完美,它的遗憾之处包括但不限于:1.不能设置背景颜色:2.虽然提供了平移功能,却未提供旋转功能与缩放功能:3.只能在控件 ...

  5. Java开发笔记(一百二十)AWT文本标签

    前面介绍了AWT窗口及其面板的简单用法,其中展示出来的控件只有按钮一种,还有很多好用好玩的控件有待介绍.首先是文本标签Label,该控件用于显示一段平铺文本,它不花哨也不跳动,完全就是素面朝天的文本字 ...

  6. Java开发笔记(一百二十六)Swing的窗口

    前面介绍了AWT界面编程的若干技术,在编码实践的时候,会发现AWT用起来甚是别扭,它的毛病包括但不限于下列几点:1.对中文的支持不好,要想在界面上正常显示汉字,还得在运行时指定额外的运行参数“-Dfi ...

  7. Java开发笔记(一百二十八)Swing的图标

    前面提过,AWT没提供能够直接显示图像的控件,这无疑是个令人诟病的短板,因为一上来就得由程序员自己去定义新控件,对于初学者来讲很不友好.这个问题在Swing中也解决掉了,不过Swing并未提供单独的图 ...

  8. Java开发笔记(一百二十二)AWT选择框

    前面介绍了两种文本输入框的用法,不过实际应用很少需要用户亲自文字,而是在界面上列出几个选项,让用户勾勾点点完成选择,这样既方便也不容易弄错.依据选择的唯一性,可将选项控件分为两类:一类是在方框中打勾的 ...

  9. Java开发笔记(一百二十九)Swing的输入框

    Swing的输入框仍然分成两类:单行输入框和多行输入框,但与AWT的同类控件相比,它们在若干细节上有所调整.首先说单行输入框,AWT的单行输入框名叫TextField,平时输入什么字符它便显示什么字符 ...

  10. Java开发笔记(九十二)文件通道的基本用法

    前面介绍的各色流式IO在功能方面着实强大,处理文件的时候该具备的操作应有尽有,可流式IO在性能方面不尽如人意,它的设计原理使得实际运行效率偏低,为此从Java4开始增加了NIO技术,通过全新的架构体系 ...

随机推荐

  1. mysql数据库表的修改及删除

    一.对数据表的修改 1.重命名一张表: RENAME TABLE 原名 TO 新名字; ALTER TABLE 原名 RENAME 新名; ALTER TABLE 原名 RENAME TO 新名; 2 ...

  2. Hadoop 排序

    数据排序是许多实际任务在执行时要完成的第一项工作,比如学生成绩评比.数据建立索引等.这个实例和数据去重类似,都是先对原始数据进行初步处理,为进一步的数据操作打好基础. 1.实例描述 对输入文件中的数据 ...

  3. Java面试题整理:这些Java程序员面试中经常遇见的题目,必须掌握才能有好结果

    1.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时 ...

  4. 什么是HTML?HTML5是什么?HTML5有那些优势和特性?

    一.什么是HTML 在了解html5之前,首先要说一下html语言,尽管是更新后的5,但很多的地方还是保留了html的优势. HTML是HyperText Markup Language超级文本标记语 ...

  5. #Java学习之路——基础阶段(第五篇)

    我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...

  6. [Swift]LeetCode111. 二叉树的最小深度 | Minimum Depth of Binary Tree

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  7. [Swift]LeetCode335. 路径交叉 | Self Crossing

    You are given an array x of n positive numbers. You start at point (0,0) and moves x[0] metres to th ...

  8. Linux 虚拟网络设备详解之 Bridge 网桥

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面几篇文章介 ...

  9. MySQL开启远程连接权限

    对于我们刚开始安装的mysql或者mariadb来说,默认是不开启远程连接的.所以需要我们手动开启远程连接的权限.如果你是使用docker安装mysql那需要先进入容器中,这里就不讲如何进入容器了,百 ...

  10. SpringCloud(4)---Ribbon服务调用,源码分析

    SpringCloud(4)---Ribbon 本篇模拟订单服务调用商品服务,同时商品服务采用集群部署. 注册中心服务端口号7001,订单服务端口号9001,商品集群端口号:8001.8002.800 ...