前面的文章提到,Date是Java最早的日期工具,估计当时的设计师是个技术宅男,未经过充分调研就拍脑袋写下了Date的源码,造成该工具存在先天不足,比如getYear方法返回的不是纯正的公元纪年、getHours方法无法区分12小时制和24小时制等等,这很不利于Java语言的国际化。故而从JDK1.1开始,Java又提供了一个日历工具Calendar,官方建议采用Calendar替代Date,并且Date的相关get方法都被标记为Deprecated(意思是已废弃)。接下来就来看看这个全新的Calendar该当如何使用。
首先,创建日历实例调用的是getInstance方法,而非new关键字,日历实例的获取代码如下所示:

		// 创建一个日历实例
Calendar calendar = Calendar.getInstance();

其次,调用日历实例的get方法,获得指定时间单位的具体数值,例如类型Calendar.YEAR对应的是公元年份,类型Calendar.MONTH对应的是月份序号等等,以年份为例,具体的获取代码如下所示:

		// 获取日历实例中的年份
int year = calendar.get(Calendar.YEAR);
System.out.println("year="+year);

从以上代码可见,此时得到的年份数值无需额外加上1900,果然比Date省事多了。不过通过Calendar获取其它时间单位仍有两点需要注意:
1、Calendar的月份依然从0开始计数,也就是说,日历工具获取的一月份数值为0,十二月份的数值为11,于是获取月份的代码需要记得加一:

		// 获取日历实例中的月份
int month = calendar.get(Calendar.MONTH)+1;
System.out.println("month="+month);

2、原来Date的星期几从0开始计数,现在Calendar的星期几改为从1开始计数,可谓一大进步,不料它的星期仍旧以星期日打头、以星期六结尾。也就是说,日历工具获取的星期日数值为1,星期一数值为2,这样一来只好由程序员手工调整,按照国人习惯把星期一对应的数值改为1、把星期日对应的数值改为7等等。修改后的星期获取代码示例如下:

		// 获取日历实例中的星期几
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
dayOfWeek = dayOfWeek==1 ? 7 : dayOfWeek-1;
System.out.println("dayOfWeek="+dayOfWeek);

其它的时间单位中规中矩,无需额外的处理,与Date相比,Calendar新增了类型Calendar.DAY_OF_YEAR(从年初开始数的日子),以及Calendar.MILLISECOND(秒钟后面的毫秒),另外把时钟区分为Calendar.HOUR(十二小时制的时钟数值)和Calendar.HOUR_OF_DAY(二十四小时制的时钟数值)两种类型。这些普通时间单位的获取代码如下所示:

		// 获取日历实例中的日子
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("dayOfMonth="+dayOfMonth);
// 获取日历实例中从年初开始数的日子
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println("dayOfYear="+dayOfYear);
// 获取日历实例中的时钟(12小时制)
int hour = calendar.get(Calendar.HOUR);
System.out.println("hour="+hour);
// 获取日历实例中的时钟(24小时制)
int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
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);

再次,Calendar提供了set方法用于设置时间数值,并且重载了参数个数不同的多种set方法,其中带三个参数的set方法支持同时设置年月日,带六个参数的set方法支持同时设置年月日、时分秒。这两种set方法的调用代码示例如下:

		Calendar calendar = Calendar.getInstance();
// 调用带三个参数的set方法同时设置日历实例的年、月、日
calendar.set(2018, 11, 27);
// 调用带六个参数的set方法同时设置日历实例的年、月、日、时、分、秒
calendar.set(2018, 11, 27, 12, 30, 40);

如果只想修改某个时间单位,则可调用带两个参数的set方法,第一个参数为单位类型包括Calendar.YEAR、Calendar.MONTH等等,第二个参数为具体的时间数值。比如以下的代码表示把某个日期改为当月1号:

		// 带两个参数的set方法允许把某个时间单位改为指定数值
calendar.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("end set dayOfMonth="+calendar.get(Calendar.DAY_OF_MONTH));

注意到以上代码设置的日期是绝对值,有时候可能需要在当前日期上增增减减,也就是设置日期的相对值,此时可以联合使用get和set方法,先通过get方法获得当前的时间数值,对当前数值增减之后再传给set方法。下面的代码便演示了设置时间相对值的实现过程:

		// 联合使用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));

联合使用get和set方法固然实现了相对时间的修改,可是简简单单的功能还得两个步骤稍显繁琐,因此Calendar另外提供了add方法,利用add方法允许直接设置相对数值,就像下列代码示范的那样:

		// 调用add方法,直接在当前时间的基础上增加若干数值
calendar.add(Calendar.MINUTE, 10); // 给当前时间加上10分钟
System.out.println("end add minute="+calendar.get(Calendar.MINUTE));

日历工具Calendar就像它的前辈Date一样,仍然保留了与时间校验相关的几个方法,包括equals、before、after、compareTo方法等,并且它们的用法与Date类型的同名方法保持一致,这里不再赘述,还是直接看下面的时间比较代码好了:

	// 比较两个日历时间的先后关系
private static void compareCalendar() {
Calendar calendarOld = Calendar.getInstance();
Calendar calendarNew = Calendar.getInstance();
// 给calendarNew加上一秒
calendarNew.add(Calendar.SECOND, 1);
// 比较两个时间是否相等
boolean equals = calendarOld.equals(calendarNew);
System.out.println("equals="+equals);
// 比较A时间是否在B时间之前
boolean before = calendarOld.before(calendarNew);
System.out.println("before="+before);
// 比较A时间是否在B时间之后
boolean after = calendarOld.after(calendarNew);
System.out.println("after="+after);
// 比较A时间与B时间的先后关系。返回-1表示A时间较早,返回0表示两个时间相等,返回1表示B时间较早
int compareResult = calendarOld.compareTo(calendarNew);
System.out.println("compareResult="+compareResult);
}

  

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

Java开发笔记(四十一)日历工具Calendar的更多相关文章

  1. Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发

    一.标准CRUD使用 对于标准的CRUD功能都有哪些以及MyBatisPlus都提供了哪些方法可以使用呢? 我们先来看张图: 1.1 环境准备 这里用的环境就是Java开发学习(四十)----MyBa ...

  2. Java开发笔记(十一)常见的数学函数

    前面介绍了Java编程的四则运算,虽然提供了基础的加减乘除符号,但是数学上还有其它运算符号,包括四舍五入用到的约等号≍.求绝对值的“| |”.开平方的“√ ̄”,这些运算符形态各异,而且并非ASCII码 ...

  3. Java开发笔记(序)章节目录

    现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...

  4. Java开发笔记(四十二)日历工具的常见应用

    前面介绍了日历工具Calendar的基本用法,乍看起来Calendar与Date两个半斤八两,似乎没有多大区别,那又何苦庸人自扰鼓捣一个新玩意呢?显然这样小瞧了Calendar,其实它的作用大着呢,接 ...

  5. Java开发笔记(七十一)容器工具Collections

    清单作为一组数据的有序队列,它在组织形式上与数组有着某些异曲同工之处,数组有专门的数组工具Arrays来进行加工操作,照理清单也应该配备对应的清单工具.当然容器这个大家族确实拥有自己的容器工具Coll ...

  6. Java开发笔记(八十一)如何使用系统自带的注解

    之前介绍继承的时候,提到对于子类而言,父类的普通方法可以重写也可以不重写,但是父类的抽象方法是必须重写的,如果不重写,编译器就直接在子类名称那里显示红叉报错.例如,以前演示抽象类用法之时,曾经把Chi ...

  7. Java开发笔记(四十三)更好用的本地日期时间

    话说Java一连设计了两套时间工具,分别是日期类型Date,以及日历类型Calendar,按理说用在编码开发中绰绰有余了.然而随着Java的日益广泛使用,人们还是发现了它们的种种弊端.且不说先天不良的 ...

  8. Java开发笔记(二十三)数组工具Arrays

    数组作为一种组合形式的数据类型,必然要求提供一些处理数组的简便办法,包括数组比较.数组复制.数组排序等等.为此Java专门设计了Arrays工具,该工具包含了几个常用方法,方便程序员对数组进行加工操作 ...

  9. Java开发笔记(四十四)本地日期时间与字符串的互相转换

    之前介绍Calendar的时候,提到日历实例无法直接输出格式化后的时间字符串,必须先把Calendar类型转换成Date类型,再通过格式化工具SimpleDateFormat获得字符串.而日期时间的格 ...

随机推荐

  1. XML语言1.简介和语法

    一.什么是XML语言? XML 指可扩展标记语言(Extensible Markup Language) Xml是独立于软件和硬件的信息传输工具. XML 是一种很像HTML的标记语言. 但xml不是 ...

  2. 小程序----选择地理位置 ( wx.chooseLocation ) 和 获取地理位置 (wx.getSetting)

    问题来了:假如我第一次使用wx.chooseLocation()获取权限被拒绝,然后使用wx.getSetting()来重新获取权限该怎么做呢? 思路:wx.chooseLocation()有fail ...

  3. Three.js学习笔记02

    1.改变相机的位置,让物体移动 通过下面的代码改变相机的位置: camera.position.x =camera.position.x +1; 将相机不断的沿着x轴移动1个单位,也就是相机向右移动. ...

  4. [转]Setting Keystone v3 domains

    http://www.florentflament.com/blog/setting-keystone-v3-domains.html The Openstack Identity v3 API, p ...

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

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

  6. [Swift]LeetCode247.对称数 II $ Strobogrammatic Number II

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  7. [Swift]LeetCode882. 细分图中的可到达结点 | Reachable Nodes In Subdivided Graph

    Starting with an undirected graph (the "original graph") with nodes from 0 to N-1, subdivi ...

  8. 上次被人说TK不好咯,这次给你整个高大上的

    0.环境 操作系统:Windows Python版本:3.6.0 1.前言 PyQt是一个创建GUI应用程序的工具包.它是Python编程语言和Qt库的成功融合.Qt库是目前最强大的库之一. 2.效果 ...

  9. HBase篇--初始Hbase

    一.前述 1.HBase,是一个高可靠性.高性能.面向列.可伸缩.实时读写的分布式数据库.2.利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量 ...

  10. 【从零开始自制CPU之学习篇00】开篇

    从今天开始决定用面包板制作一个8位的CPU,实现几个简单的指令.我给自己分两大部分计划,第一部分是学习制作CPU的理论知识,第二部分是实践.并打算实施计划的同时用博客的方式记录下来.理论知识的部分重点 ...