从零开始学Java之时间相关的类有哪些?
一. 概念简介
在开始学习今天的知识之前,有必要先给大家讲解一下与今天内容相关的一些概念,否则可能会让一些小白产生迷惑。
日期和时间的区别
首先我们得搞清楚,日期和时间的概念并不一样。日期是指某一天,它不是连续变化的,可以说是离散的。而时间有两种概念,一种是不带日期的时间,如10:30:01;另一种是带日期的时间,如2023-01-01 15:11:40。只有带日期的时间,才能唯一确定某个时刻,而不带日期的时间是无法确定一个唯一时刻的。
本地时间
本地时间其实就是每个地方,当前所在国家所采用的标准时间。比如我们国家就是采用的北京时间,只要是在中国大陆,我们说晚上8:00见,这个8:00指的就是北京时间。即使我们国家的时区,其实包括了从东五区到东九区共5个时区,但我们全国都是统一采用的东八区的区时,这样各地区人员之间的交流才不会产生歧义。但如果是在别的国家,那这个本地时间,就是他们国家的标准区时了,所以每个国家的标准区时可能是不同的。
时区表示法
我们初中学地里的时候,就学过时区的概念,壹哥这里就不多讲了。在计算机中,如果我们想准确地确定一个时间,需要把本地时间和时区结合在一起才行。其中时区有如下几种表示方式:
3.1 GMT或UTC加时区偏移表示法:如GMT+08:00 或 UTC+08:00,就表示东八区的时间。因为北京时区是东八区,领先UTC 8个小时,所以将UTC装换成北京时间时,要加上8小时。GMT(Greenwich Mean Time)是格林威治标准时间,UTC(Universal Time Coordinated)是世界统一时间或世界标准时间,GMT和UTC其实基本是等价的,它们都是英国伦敦的本地时间。但UTC使用了更精确的原子钟计时,每隔几年会有一个闰秒,不过我们在开发时可以忽略两者的误差,因为计算机的时钟在联网时会自动与时间服务器同步时间。
3.2 时区缩写表示法:如CST是China Standard Time的缩写,即中国标准时间。但CST也是美国中部时间Central Standard Time USA的缩写,因此有些缩写容易产生混淆,开发时尽量不要使用缩写形式。
3.3 洲/城市表示法:如Asia/Shanghai,表示上海所在地的时区。我们要特别注意,城市名称并不是任意的城市,而是由国际标准组织规定的城市。
本地化
本地化并不只包括时间这一种信息,还包括一个国家或地区所采用的日期、时间、数字、货币等各种信息的格式,开发时通常使用Locale进行表示。Locale由“语言_国家”的字母缩写构成,如“zh_CN”就表示“中文+中国”,“en_US”表示“英文+美国”。其中语言是小写,国家是大写。
而对于不同国家或地区的Locale日期部分来说,如中国和美国的本地时间表示方式如下:
● zh_CN:2023-01-24
● en_US:01/24/2023
夏令时
夏令时(Daylight Saving Time:DST),也叫夏时制,又称“日光节约时制”,是一种为了节约能源而人为规定地方时间的制度。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。
我们国家曾经实行过一段时间夏令时,但在1992年就废除了,不过美国人到现在还在使用。所以涉及到跨国应用开发时,相关时间的换算可能会有点复杂。因为涉及到夏令时,相同的时区,如果表示的方式不同,转换出的时间也是不同的。
Epoch Time时间起点
Epoch Time是一个固定的通用时间,即世界标准时间(UTC) 1970-01-01 00:00:00 UTC,它是计算机里时间开始的起点,该起点被记为0,而1970年以前的时间被认为是负数。我们知道,现实世界的时间谁也不知道是从什么时候开始的,但是计算机发明的时间并不长,为了方便大家进行各种开发和计算,于是国际标准委员会就给计算机设置了一个时间的起点。以这个时间为起点,每过去一秒,该数值就加1,这样我们就可以算出对应的公历时间日期(不包括闰秒)。Epoch Time在不同的编程语言中,会有几种不同的存储方式:
● 以秒为单位的整数:1574208900,缺点是精度只能到秒;
● 以毫秒为单位的整数:1574208900123,最后3位表示毫秒数;
● 以秒为单位的浮点数:1574208900.123,小数点后表示零点几秒。
时间戳
时间戳(timestamp),也称为Unix时间 或 POSIX时间,它是一种时间表示方式。表示从1970年1月1日0时0分0秒(格林尼治时间)开始,一直到现在所经过的秒数或毫秒数。在Java一般是用long类型来存储该值,但在别的编程语言中有可能是使用float类型。比如1574208900就表示从1970年1月1日零点开始,到2019年11月20日8点15分截止,一共经历了1574208900秒,所以换算成北京时间就是:1574208900 = 北京时间2019-11-20 8:15:00。如果我们要获取当前的时间戳,在Java中可以使用System.currentTimeMillis()方法。
从本质上来说,时间戳就是个时间差值,其值与时区无关。比如在UTC标准下,时间起点的时间戳就是timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00,此时对应的北京时间是timestamp = 0 = 1970-1-1 08:00:00 UTC+8:00
了解了以上这些基本概念之后,我们就可以继续往下学习今天其他的内容了。
二. Date日期时间类
简介
如果我们想在Java中获取当前的时间,可以使用 java.util.Date类 和 java.util.Calendar类来实现。其中,Date类封装了系统的日期和时间信息,Calendar类则会根据系统的日历来填充Date对象。
java.util.Date是一个表示日期和时间的类,代表了系统特定的时间戳。它是按照UTC时间显示的,可以精确到毫秒,源码内部使用long类型进行时间的存储。我们要注意与java.sql.Date区分,后者是用在数据库中的类,且是按照本地时区显示的。Date对象表示的时间,其默认顺序是星期、月、日、小时、分、秒、年。
构造方法
java.util.Date类给我们提供了多个构造方法,如下图所示:
但是一般在开发时,我们常用的也没有这么多,一般使用时如下形式:
● Date():创建Date对象并初始化,该对象可以获取本地的当前时间,该时间会精确到毫秒。
● Date(long date):构造一个Date对象,并接受一个从1970年1月1日起的毫秒数作为参数。
常用API方法
当我们构造出来一个Date对象之后,就可以使用它的一些API方法进行时间的操作了,这些常用的API方法如下:
使用方法
4.1 基本使用
接下来我们先通过一个简单的案例,来演示一下Date的基本用法。
import java.util.Date;
/**
* @author 一一哥Sun
*/
public class Demo01 {
public static void main(String[] args) {
//获取当前时间的时间戳
long currentTimeMillis = System.currentTimeMillis();
System.out.println("时间戳="+currentTimeMillis);
//获取当前时间对象
Date date=new Date();
//Sat Feb 11 12:04:03 IRKT 2023
System.out.println("当前时间="+date);
//转为字符串:Sat Feb 11 12:04:03 IRKT 2023
System.out.println("当前时间="+date.toString());
//转换为本地时区:2023年2月11日 下午12:04:03
System.out.println("当前时间,Locale="+date.toLocaleString());
//转换为GMT时区:11 Feb 2023 04:04:03 GMT
System.out.println("当前时间,GMT="+date.toGMTString());
}
}
如果我们想获取当前时间的时间戳,可以使用System.currentTimeMillis()方法。构造出Date对象之后,我们可以直接打印该对象,就能展示出当前时间,但是这个格式并不一定符合我们中国人的阅读习惯,后面我们可以对日期进行格式化操作。
4.2 其他用法
除了上面这些基本用法之外,Date还有其他的一些用法。
import java.util.Date;
/**
* @author 一一哥Sun
*/
public class Demo01 {
public static void main(String[] args) {
//获取当前时间对象
Date date=new Date();
//获取年月日
System.out.println("年="+(date.getYear() + 1900)); // 必须加上1900
System.out.println("月="+(date.getMonth() + 1)); // 0~11,必须加上1
System.out.println("日="+date.getDate()); // 1~31,不能加1
System.out.println("时="+date.getHours()); // 0~23
System.out.println("分="+date.getMinutes()); // 0~59,不能加1
System.out.println("秒="+date.getSeconds()); // 0~59,不能加1
System.out.println("时间戳="+date.getTime()); // 时间戳,毫秒值
//计算自己已经活了多少天,1990年01月31日
//构造对象的另一个方法,已过时。year:要减去1900,月份从0开始,0-11;日期是1-31
Date d1 = new Date(1990-1900, 2-1, 31);
Date d2 = new Date();
long time = d2.getTime() - d1.getTime();
System.out.println("已活天数="+time/1000/60/60/24);
}
}
另外我们还要注意,getYear()方法返回的年份必须加上1900;getMonth()方法返回的月份是011,分别表示112月,所以要加1;而getDate()方法返回的日期范围是1~31,就不能加1。
在打印本地时区表示的日期和时间时,不同的计算机可能会有不同的展示结果,后面我们可以使用SimpleDateFormat设置出我们想要的日期时间格式。
4.3 统计时间差
有时候我们要统计某个功能的执行时间,此时就可以用该功能结束时的时间,减去开始时的时间,得到一个时间差,这就是该功能的执行时间。
import java.util.Date;
/**
* @author 一一哥Sun
*/
public class Demo03 {
public static void main(String[] args) {
//获取当前时间对象
//开始时间
Date startDate=new Date();
for(int i=0;i<100000;i++) {
System.out.println("循环次数"+i);
}
//结束时间
Date endDate=new Date();
//计算时间差
long time = endDate.getTime() - startDate.getTime();
System.out.println("10w次循环的执行时间是 "+time+" 毫秒");
}
}
三. Calendar日历类
简介
Calendar类是Java时间类Date的扩展。相比Date,它拥有更强大的功能,主要是多了可以做简单日期和时间运算的功能,且在实现方式上也比Date类更复杂一些。Calendar可以用来计算日期,比如说计算下个月的日期,或者两个月前的日期等。
Calendar类是一个抽象类,我们在实际使用时需要实现特定的子类,一般使用getInstance()方法创建即可。Calendar类有几个主要的子类,包括java.util.GregorianCalendar和java.util.TimeZone。其中GregorianCalendar类提供了标准的日历系统,可以用来计算未来或过去某天的日期。TimeZone类则可以用来在不同的时区之间,转换日期和时间。
Calendar常量字段
Calendar中有以下几个常用的常量字段,用于表示不同的意义。
Calendar常用方法
除了以上常用的常量字段之外,Calendar还有一些常用的方法,如下表所示:
Calendar对象可以调用set()方法将日历翻到任何一个时间,当参数 year取负数时表示是公元前。调用 get()方法可以获取年、月、日等时间信息,field参数的值是前面讲过的Calendar静态常量。
构建Calendar对象
Calendar类是抽象类,所以我们不能通过new的方式来构建Calendar对象。在实际使用时,我们一般是要实现特定的子类,经常是使用getInstance()方法进行创建。
import java.util.Calendar;
/**
* @author 一一哥Sun
*/
public class Demo04 {
public static void main(String[] args) {
//默认是当前日期
Calendar c1 = Calendar.getInstance();
System.out.println("c1="+c1);
//创建一个代表2023年2月2日的Calendar对象
Calendar c2 = Calendar.getInstance();
c2.set(2023, 2-1, 2);
System.out.println("c2="+c2);
}
}
获取当前时间
获取到Calendar对象之后,我们可以获取到当前日期对象的年月日时分秒等信息。
import java.util.Calendar;
/**
* @author 一一哥Sun
* V我领资料:syc_2312119590
* 各平台都有壹哥的同名博客哦
*/
public class Demo05 {
public static void main(String[] args) {
// 获取当前时间
Calendar c = Calendar.getInstance();
int y = c.get(Calendar.YEAR);
//月份要加1
int m = 1 + c.get(Calendar.MONTH);
int d = c.get(Calendar.DAY_OF_MONTH);
int w = c.get(Calendar.DAY_OF_WEEK);
int hh = c.get(Calendar.HOUR_OF_DAY);
int mm = c.get(Calendar.MINUTE);
int ss = c.get(Calendar.SECOND);
int ms = c.get(Calendar.MILLISECOND);
//2023-2-11 7 18:10:59.847
System.out.println(y + "-" + m + "-" + d + " " + w + " " + hh + ":" + mm + ":" + ss + "." + ms);
}
}
我们要注意,Calendar是通过get()方法获取年月日等信息的,其中返回的年份不必转换,返回的月份仍要加1,返回的星期要特别注意,1~7分别表示周日、周一、……周六。
6. 设置时间
我们通过Calendar.getInstance()方法获取到Calendar对象后,获取到的其实就是当前时间。如果我们想设置某个特定的日期和时间,需要先用clear()方法清除掉之前所有的字段。
import java.util.Calendar;
/**
* @author 一一哥Sun
*/
public class Demo06 {
public static void main(String[] args) {
// 设置时间
Calendar c = Calendar.getInstance();
// 清除所有
c.clear();
// 设置2023年
c.set(Calendar.YEAR, 2023);
// 设置2月(0~11)
c.set(Calendar.MONTH, 1);
// 设置2日
c.set(Calendar.DATE, 2);
// 设置时间
c.set(Calendar.HOUR_OF_DAY, 21);
c.set(Calendar.MINUTE, 22);
c.set(Calendar.SECOND, 23);
//Thu Feb 02 21:22:23 IRKT 2023
System.out.println("date="+c.getTime());
}
}
我们可以利用Calendar.getTime()方法,将一个Calendar对象转换成Date对象,后面我们就可以用SimpleDateFormat进行格式化操作了。
四. GregorianCalendar类
简介
Java中除了有Calendar类实现了公历日历,还有一个子类GregorianCalendar。在GregorianCalendar类中,定义了两个字段:AD和BC,分别代表公历定义的两个时代。GregorianCalendar中的属性和方法与Calendar类似,壹哥就不再赘述了,接下来我们直接通过一个案例来进行展示其用法。
基本用法
这里我们设计一个案例,来判断当前年份是闰年还是平年。
import java.util.Calendar;
import java.util.GregorianCalendar;
/**
* @author 一一哥Sun
*/
public class Demo05 {
public static void main(String[] args) {
//定义一个月份数组
String months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int year;
// 使用当前时间和日期,初始化Gregorian日历对象,默认为本地时间和时区
GregorianCalendar gcalendar = new GregorianCalendar();
// 显示当前时间和日期的信息
System.out.print("Date:");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time:");
System.out.print(gcalendar.get(Calendar.HOUR) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
//判断当前年份是否为闰年
if (gcalendar.isLeapYear(year)) {
System.out.println("当前年份是闰年");
} else {
System.out.println("当前年份是平年");
}
}
}
猜你喜欢LIKE
相关推荐HOT
更多>>servlet底层原理是什么?
1、ServletAPI核心类与接口2、Servlet类处理请求的流程创建servlet类的步骤:创建一个命名为TestServlet继承javax.servlet.http.HttpServlet类详情>>
2023-05-30 10:41:22多线程的优势与劣势分别是什么?
多线程是指在同一个程序中,同时运行多个线程,每个线程都可以独立执行不同的任务,相互之间不会干扰。多线程的优势和劣势如下:优势:提高程序...详情>>
2023-05-30 10:32:12设计模式之生产者与消费者的代码实现
本文主要讲述生产者和消费者模式,文中会使用通俗易懂的案例,使你更好地学习本章知识点并理解原理,做到有道无术。什么是生产者和消费者模式生...详情>>
2023-05-30 10:25:46从零开始学Java之interface接口
一.接口简介简介Java中的接口(interface)类似于是一种特殊的抽象类,它也是众多抽象方法的集合。接口的定义方式、组成部分都与抽象类相似,却比...详情>>
2023-05-29 11:26:17热门推荐
如何进行mysql数据备份?
沸什么是servlet的生命周期?servlet请求处理流程是怎样的?
热servlet底层原理是什么?
热怎样编写java程序?
新多线程的优势与劣势分别是什么?
ssm框架的作用与原理是什么?
设计模式之生产者与消费者的代码实现
接口和抽象类有什么区别?4个方面对比
从零开始学Java之interface接口
从零开始学Java之Java中的内部类是怎么回事?
一分钟带你了解MySQL——基础与介绍
在java中,super关键字怎样使用
什么是事件流以及事件流的传播机制 ?
弹性盒有哪些属性是在父元素身上?