Java中的日期——Date、SimpleDateFormat、Calendar

Date
java.util包下的类 Date 表示特定的瞬间,精确到毫秒。
在 JDK 1.1 之前,类 Date 有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过,这些函数的 API 不易于实现国际化。从 JDK 1.1 开始,应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串。Date 中的相应方法已废弃。
ps:毫秒值的作用:可以对时间和日期进行计算
譬如:求2099-01-03到2088-01-01中间一共有多少天
可以将日期转换为毫秒进行计算,计算完毕再把毫秒转换为日期
把日期转换为毫秒:
当前日期:2088-01-01,将其转换为毫秒,所得的毫秒值本质上是以时间原点作为参照,计算某个时间的毫秒值就是计算某个时间到时间原点之间一共经历了多少毫秒
1天=24✖60✖60=86400秒=86400000(毫秒)
时间原点(0毫秒):1970年1月1日 00:00:00 (英国格林威治)
中国属于东八区,会把时间增加8个小时 1970年1月1日 08:00:00

package com.jinglan.data;

public class Demo {
	public static void main(String[] args) {
		long current = System.currentTimeMillis();
		System.out.println(current);// 打印出当前的系统时间
	}

}

运行结果为:1615937334695

也就是说当前的时间为1615937334695毫秒,而这个毫秒值的意思是指,从1970年1月1日 00:00:00到现在一共经历了1615937334695毫秒

Date类中的一些方法:
构造方法:
空参构造方法:
返回的是当前的系统时间

package com.jinglan.data;
import java.util.Date;
public class Demo {
	public static void main(String[] args) {
		Date date = new Date();
		System.out.println(date);
	}

}

运行结果:Wed Mar 17 07:54:35 CST 2021

带参构造方法:
传递一个毫秒值,返回的是一个日期值

package com.jinglan.data;
import java.util.Date;
public class Demo {
	public static void main(String[] args) {
		Date date = new Date(0L);//传入一个参数0毫秒,应该返回出时间原点
		System.out.println(date);
	}

}

运行结果:Thu Jan 01 08:00:00 CST 1970

又如传递一个其它的毫秒值:
3255689232970L得到的日期值是:Thu Mar 02 22:07:12 CST 2073
成员方法:
getTime()将日期格式转换为毫秒形式
补充:System.currentTimeMillis()方法是用来返回当前系统时间的,且返回的数据类型是长整型的毫秒值

通过前面的介绍我们已经学会了获取当前的系统时间,但会发现系统的时间是按照外国的时间习惯来表示的,如何才能把时间转变成为我们中国人熟悉的时间格式?这就需要用到SimpleDateFormat类
SimpleDateFormat类
最开始的时候我们说过,由于版本的更新现在是由 DateFormat 类来格式化和解析日期字符串。这句话的意思是说,要想把外国人的时间表示习惯转换成我们中国人了解的时间表示习惯就需要用到格式化和解析日期
这里的格式化就是指:将系统时间格式化为我们习惯的时间表示,解析就是指将我们习惯的时间表示解析为系统的时间表示
在Java中有一个类是专门用来处理格式化和解析的问题的,不只是格式化时间还有格式化数字格式化消息它就是java.text包下的Format类,它是一个抽象类继承自Object类,它的下面有DateFormat、MessageFormat、NumberFormat子类,这里就不做过多的赘述。
DateFormat类就是专门用来格式化和解析日期的类,它里面提供了两个很重要的成员方法:String format(Date date)方法和Date parse(String source)方法,这两个方法就是用来实现格式化和解析日期的核心方法。但是由于DateFormat是一个抽象类,我们无法直接创建对象来使用,所以我们常使用它的子类——SimpleDateFormat类来实现格式化和解析日期的操作。
**SimpleDateFormat中的构造方法——SimpleDateFormat(String pattern)其中小括号里的参数表示的是一个描述日期和时间指定模式的字符串。**那么问题来了?这个模式又是一种怎样的模式或者说标准呢,怎样写才能符合模式?
接下来针对这个模式问题做一个拓展:
在这里插入图片描述
在日期模式中是严格区分大小写的
一般情况下我们只用得到
y 年
M 月
d 日
H 时
m 分
s 秒
比如yyyy-MM-dd HH-mm-ss、yyyy年MM月dd日HH时mm分ss秒…
ps:只要字母不出现问题,字母中间的连接符可随意编写。

format()、parse()方法
既然格式化和解析时间最核心的就是String format(Date date)和Date parse(String source)方法,那我们就针对这两个方法做一些详细的了解
现在有一个需求——获取当前的系统时间,并将该时间转换为我们中国人熟悉的时间表示即格式化当前系统的时间
ps:当然也不一定非要是系统时间也可以是随意的一个时间只要跟系统时间一样的模式就好
需求分析:1、首先我们需要获取一个系统时间 前面介绍过的有Date类的空参构造方法可以获取也有getTime()和System.currentTimeMillis()方法可以获取,但是为了更简洁,我们采用Date类的空参构造来获取这样的方式对我们这一道题更友好,采用其它两种方法也可以只是format()方法和parse()方法涉及的是Date类型和String类型的,Date类的空参构造方法就是Date类型的,getTime()和System.currentTimeMillis()最终返回的Long类型会涉及到类型转换,所以为了很快地解决问题我们选用Date类的空参构造方法来获取当前的系统时间。2、创建SimpleDateFormat对象,同时在其构造方法中传入你想要系统时间转换成的日期模式。
3、利用SimpleDateFormat对象调用format()方法、传入系统时间(也就是需要转换格式的时间)
4、打印查看转换效果

package com.jinglan.data;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
	public static void main(String[] args) {
		Date date = new Date();// 获取系统时间
		// 查看一下没有格式化之前的系统时间
		System.out.println(date);// date就是当前的系统时间
		// 现在将这个时间进行格式化
		// 创建SimpleDateFormat对象,同时在其构造方法中传入你想要系统时间转换成的日期模式。
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
		// 利用SimpleDateFormat对象调用format()方法、传入系统时间(也就是需要转换格式的时间)
		String formattime = sdf.format(date);
		System.out.println(formattime);// 打印查看转换效果

	}

}

运行结果:
在这里插入图片描述
接着是parse()方法的介绍:
同样的既然我们将系统时间格式转化为了我们熟悉的时间格式,也可以反过来将我们熟悉的时间格式转回为外国人能看得懂的系统时间格式
现在有一个需求——将一个被格式化了的时间转化回原来的格式(其实就是把中国人熟悉的时间格式转换回外国人熟悉的时间格式)
需求分析1、首先我们需要一个时间这个时间是被格式化了的时间
2、创建SimpleFormatDate对象,同时在其构造方法中传入我们格式化过了的时间的模式
3、利用SimpleDateFormat对象调用parse()方法、传入与SimpleDateFormat构造方法中模式一样的时间
4、打印查看效果

package com.jinglan.data;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
	public static void main(String[] args) {
		// 创建SimpleFormatDate对象,同时在其构造方法中传入我们格式化过了的时间的模式
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		try {//有个异常后面介绍
			Date parse = sdf.parse("2000-01-03 18-45-53");// 括号里的时间的模式一定要跟SimpleDateFormat方法里的时间的模式一样否则就会报出解析异常parseException
			System.out.println(parse);// 打印查看效果
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

运行结果:
在这里插入图片描述
介绍一下 parse()方法的parseException异常问题,通过查阅底层代码可以看到parse()方法本身声明了一个parseException解析异常,如果意为:如果我们传入的字符串,它的模式不与SimpleDateFormat()构造方法中传入的模式一致就会抛出parseException异常
如下例
在这里插入图片描述
运行结果:
在这里插入图片描述
对于一个本身就声明了异常的方法 有两个解决方法 第一:一劳永逸使用这个方法时 将其try…catch自己处理掉;第二:利用throws层层抛出最终交给虚拟机处理。在parse()例子中,我采用了try-catch的方法。

根据上述的全部内容 延伸一个练习:
需求:计算一个人出生了多少天?
需求分析:计算一个出生了多少天只需要知道这个人此时此刻的毫秒值、然后再知道他出生时的毫秒值,前者减去后者

package com.jinglan.data;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Demo {
	public static void main(String[] args) {
		// 为了友好用户 采用键盘输入的形式获取出生日期
		System.out.println("请输入您的出生日期 格式为 yyyy-MM-dd");
		Scanner sc = new Scanner(System.in);
		String birthday = sc.next();
		// 将键盘获取到的出生日期转换为日期对象,获取到的出生日期是一个字符串要转换为Date格式
			// 第一步
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			// 第二步
		Date birthdayDate = null;
		try {
			birthdayDate = sdf.parse(birthday);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 把Date格式的出生日期转换为毫秒值
		long birthdayDateMillis = birthdayDate.getTime();
		System.out.println("出生日期的毫秒值" + birthdayDateMillis);// 打印出来看一下
		// 获取当前的日期并将其转换为毫秒值
			// 方法有很多
				/*
				 * Date空参获取、getTime()、System.currentTimeMillis()
				 */
			// 为了回顾知识用最基础的方法演示
		// 创建Date
		Date date = new Date();
		long todayDateMillis = date.getTime();
		System.out.println("现在时间的毫秒值" + todayDateMillis);// 打印出来看一下
		// 计算
		long toatlMillis = todayDateMillis - birthdayDateMillis;
		// 将毫秒值转换为天数(毫秒值/1000/60/60/24)
		long days = toatlMillis / 1000 / 60 / 60 / 24;
		System.out.println("您从出生到现在一共经历了" + days + "天");

	}

}

运行结果:
在这里插入图片描述

Calendar类
java.util包下的类Calendar是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。简单来说就是JDK1.1以前Date类中的某些方法全都由Calendar类接手了,所以Date类里的很多方法都过时了。
在这里插入图片描述
时间方面的计算涉及了很多 Calendar类就是一个很好的工具
要使用Calendar类中的方法,最好是有一个Calendar对象,但是Carlendar类是一个抽象类,它虽然也有子类,但是我们一般情况下不使用它的子类来创建对象,而是使用一个方法 getInstance(),这是一个静态方法,由于我们导入了java.util.Calendar所以可以直接用类名调用这个方法即:Calendar.getInstance(),对于其它的非静态的方法,就需要用到Calendar对象,而Calendar.getInstance()的返回类型就是Calendar对象,这一点正是体现了‘多态’——(父类引用指向子类对象)。需要补充的一点就是Calendar.getInstance()准确来说返回的是一个默认时区和语言环境的日历。
下面进行原理的实现:

package com.jinglan.data;

import java.util.Calendar;

public class Demo {
	public static void main(String[] args) {
		//获取一个Calendar对象
		Calendar c = Calendar.getInstance();//多态
		System.out.println(c);//打印出来看看是个啥

	}

}

运行结果:

java.util.GregorianCalendar[time=1615950080944,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2021,MONTH=2,WEEK_OF_YEAR=12,WEEK_OF_MONTH=3,DAY_OF_MONTH=17,DAY_OF_YEAR=76,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=11,HOUR_OF_DAY=11,MINUTE=1,SECOND=20,MILLISECOND=944,ZONE_OFFSET=28800000,DST_OFFSET=0]

正常来说 一个打印类或者说是对象 返回的应该是这个 类的地址@哈希值,但上面对于Calendar对象的打印输出却不是这样的形式,可以看出其实Calendar类重写了toString()方法。里面从各个时间角度介绍了当前的日历。还有时区等等。

Calendar类中的一些方法
前面通过打印Calendar对象我们发现返回了从不同角度返回的一大串的日历信息,如果我们想要查找某一条信息,肉眼去看就感觉体验不是很好,于是为了解决这样的一个问题,我们就需要学习一个**方法get() 全称:public int get(int field)**它是Calendar类中定义的一个成员方法。
意思是传入给定的int类型的日历字段的参数,返回给定日历字段的值
field - 给定的日历字段。
返回:
给定日历字段的值。
那么问题来了 要传入给定的日历字段,那日历字段长啥样?怎样的日历字段才是系统能识别的呢?
在Calendar类中定义了一些静态的成员变量
在这里插入图片描述

字段值含义
YEAR
MONTH月(从0开始,可以+1使用)
DAY_OF_MONTH月中的天(几号)
HOUR时(12小时制)
HOUR_OF_DAY时(24小时制)
MINUTE
SECOND
DAY_OF_WEEK周中的天(周几,周日为1,可以-1使用)

解释一下:月
在西方只有0-11月,在中国是1-12月
所以系统默认返回的月份是西方的月份

package com.jinglan.data;

import java.util.Calendar;

public class Demo {
	public static void main(String[] args) {
		// 获取一个Calendar对象
		Calendar c = Calendar.getInstance();
		// Calendar类中的方法们
		// get()方法——返回指定字段代表的值,关键在于参数(字段)的传入
		int i = c.get(1);// 或者 int i = c.get(Calendar.YEAR)  如果能记住对应的数字表示的意思 也可以直接写数字 记不住数字就只能采用类名.称员变量的方式了。
		int I = c.get(Calendar.YEAR);//YEAR本身就是Calendar类中定义的静态方法,所以可以直接用Carlendar.的方式调用
		System.out.println(i);// 2021
		System.out.println(I);// 2021

	}

}

运行结果:
2021
2021

类似的其它参数演示:

package com.jinglan.data;

import java.util.Calendar;

public class Demo {
	public static void main(String[] args) {
		// 获取一个Calendar对象
		Calendar c = Calendar.getInstance();// 多态
		// Calendar类中的方法们
		// get()方法——返回指定字段代表的值,关键在于参数(字段)的传入
	    /*
	     * public static final int ERA = 0;
	     * public static final int YEAR = 1;
           public static final int MONTH = 2;
           public static final int WEEK_OF_YEAR = 3;
           public static final int WEEK_OF_MONTH = 4;
		   public static final int DATE = 5;
		   public static final int DAY_OF_MONTH = 5;
		   public static final int DAY_OF_YEAR = 6;
		   public static final int DAY_OF_WEEK = 7;
		   public static final int DAY_OF_WEEK_IN_MONTH = 8;
		   public static final int AM_PM = 9;
		   public static final int HOUR = 10;
		   public static final int JANUARY = 0;
		   ............................
		   .............................
	     */
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);//西方的月是0-11月,中国的是1-12月 如果想要友好一点加一即可
		int day = c.get(Calendar.DAY_OF_MONTH);
		int hour = c.get(Calendar.HOUR);
		int week = c.get(Calendar.WEEK_OF_MONTH);
		int dayOfYear = c.get(Calendar.DAY_OF_YEAR);
		System.out.println(year+"年"+(month+1)+"月"+day+"日");
		System.out.println(hour+"时");
		System.out.println("星期"+week);
		System.out.println("一年中的第"+dayOfYear+"天");

		

	}

}

运行结果:
20213174时
星期3
一年中的第76

方法set(),全称:public void set(int field,int value)
意思是:对自己指定的日历字段(file)自定义值(value)

package com.jinglan.data;

import java.util.Calendar;

public class Demo {
	public static void main(String[] args) {
		// 获取一个Calendar对象
		Calendar c = Calendar.getInstance();// 多态
		// Calendar类中的方法们
		// get()方法——返回指定字段代表的值,关键在于参数(字段)的传入
	    /*
	     * public static final int ERA = 0;
	     * public static final int YEAR = 1;
           public static final int MONTH = 2;
           public static final int WEEK_OF_YEAR = 3;
           public static final int WEEK_OF_MONTH = 4;
		   public static final int DATE = 5;
		   public static final int DAY_OF_MONTH = 5;
		   public static final int DAY_OF_YEAR = 6;
		   public static final int DAY_OF_WEEK = 7;
		   public static final int DAY_OF_WEEK_IN_MONTH = 8;
		   public static final int AM_PM = 9;
		   public static final int HOUR = 10;
		   public static final int JANUARY = 0;
		   ............................
		   .............................
	     */
		//设置年
		c.set(Calendar.YEAR, 1999);//也就是c.set(1, 1999);
		System.out.println(c.get(Calendar.YEAR));//查看
		//设置月
		c.set(Calendar.MONTH,7);//7月 之前设置过month+1所以这里的月份没有按照原来的输出
		System.out.println(c.get(Calendar.MONTH));
		//设置日
		c.set(Calendar.DAY_OF_MONTH,6);
		System.out.println(c.get(Calendar.DAY_OF_MONTH));
		//可以同时设置年月日
		c.set(1998, 4, 18);//调用c.set(year, month, date)方法
		System.out.println(c.get(Calendar.YEAR));
		System.out.println(c.get(Calendar.MONTH));
		System.out.println(c.get(Calendar.DAY_OF_MONTH));
		
		

	}

}

运行结果:
1999
7
6
1998
4
18

方法add(),全称:public abstract void add(int field,int amount)
意思是:把指定的日历字段(filed)增加或者减少自定义的值(amount)
如果传递的amount是一个正数则代表增加,将指定日历字段增加相应的值
如果传递的amount是一个负数则代表减少,将指定的日历字段减少相应的值

package com.jinglan.data;

import java.util.Calendar;

public class Demo {
	public static void main(String[] args) {
		// 获取一个Calendar对象
		Calendar c = Calendar.getInstance();// 多态
		// Calendar类中的方法们
		// get()方法——返回指定字段代表的值,关键在于参数(字段)的传入
	    /*
	     * public static final int ERA = 0;
	     * public static final int YEAR = 1;
           public static final int MONTH = 2;
           public static final int WEEK_OF_YEAR = 3;
           public static final int WEEK_OF_MONTH = 4;
		   public static final int DATE = 5;
		   public static final int DAY_OF_MONTH = 5;
		   public static final int DAY_OF_YEAR = 6;
		   public static final int DAY_OF_WEEK = 7;
		   public static final int DAY_OF_WEEK_IN_MONTH = 8;
		   public static final int AM_PM = 9;
		   public static final int HOUR = 10;
		   public static final int JANUARY = 0;
		   ............................
		   .............................
	     */
		//获取系统当前时间作比较
		System.out.println(c.get(Calendar.YEAR));//2021
		//将系统当前时间增加两年
		c.add(Calendar.YEAR, 2);//2023
		//再次获取当前的系统时间发生了变化
		System.out.println(c.get(Calendar.YEAR));
		//类似的可以对其他常量进行操作
		System.out.println(c.get(Calendar.MONTH));//获取当前系统的月份 2 ( 西方)
		c.add(Calendar.MONTH, -1);//将月份减少一个月 变成1
		System.out.println(c.get(Calendar.MONTH));
		
		
		

		
		

	}

}

运行结果:
2021
2023
2
1

方法getTime(),全称public final Date getTime()
意思是:将日历对象转换为日期对象

package com.jinglan.data;

import java.util.Calendar;
import java.util.Date;

public class Demo {
	public static void main(String[] args) {
		// 获取一个Calendar对象
		Calendar c = Calendar.getInstance();// 多态
		Date time = c.getTime();
		System.out.println(time);

	}

}

运行结果:
在这里插入图片描述

补充:将系统的时间格式改为中国人爱看的格式,除了SimpleDateFormat之外还可以 在创建了Date对象之后直接调用toLocalString()方法,这个方法意思是指,按照本地(电脑)的时间显示格式转换系统时间的格式
例如

package com.jinglan.data;

import java.util.Calendar;
import java.util.Date;

public class Demo {
	public static void main(String[] args) {
		Date date = new Date();
		System.out.println(date.toLocaleString());

	}

}

运行结果:
在这里插入图片描述

总结:

使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立志Java工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值