目录
2. DateFormat & SimpleDateFormat
c. DateFormat 和SimpleDateFormat 的区别
ⅱ. SimpleDateFormat简单日期格式化类的使用
ⅲ. 使用SimpleDateFormat解析字符串时间成为日期对象
a. LocalDate & LocalTime & LocalDateTime
b. DateTimeFormatter(时间格式化与解析)
e. TemporalAdjuster & TemporalAdjusters(时间校正器)
一、第一代日期类(Date,DateFormat)
1. Date
a. 简介
一般常用的是Java.util.Date包下的Date类,在java.sql.Date包下也有一个Date类,sql包下的Date
类主要用于和数据库打交道,其内容只包括日期,没有时间,util包下的Date类用于平常日期使
用,其内容包括日期和时间。
Date类表示系统特定的时间戳,可以精确到毫秒。
Date类中的大部分方法都过时了或者被Calendar类中的方法所取代
b. 常用API
c. 构造方法
Date类有两个构造方法,Date对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。
- 无参构造方法Date():此种形式表示分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒,使用该构造方法创建的对象可以获取本地的当前时间。
示例代码如下:
Date d1=new Date();
System.out.println(d1);//可以输出本地的当前时间
- 带参构造方法Date(long date):此种形式表示分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数(也就是从GMT(格林尼治时间)时间1970年1月1日0时0分0秒开始经过参数date指定的毫秒数)。
示例代码如下:
long date = 24*60*60*1000;//1秒=1000毫秒,该时间为一天24小时
Date d2 = new Date(date);
System.out.println(d2);//输出从GMT基准时间过了一天后的时间
//输出:Fri Jan 02 08:00:00 CST 1970(中央标准时间)
d. 常用方法
boolean after(Dtae when)
boolean after(Dtae when)方法的Date对象是否在指定日期之后
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.after(d1));//输出:false
boolean before(Dtae when)
判断判断调用此方法的Date对象是否在指定日期之前
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.before(d1));//输出:true
compareTo(Date date)
比较当前调用此方法的Date对象与指定日期,两者相等时返回0,调用对象在指定日期之前则返回负数,
反之返回正数
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.compareTo(d1));//输出:-1
equals(Object date)
当调用此方法的Date对象和指定日期相等时返回true,否则返回false
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.equals(d1));//输出:false
getTime()
返回自1970年1月1日0时0分0秒GMT以来此Date对象表示的毫秒数
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.getTime());//输出:86400000=24*60*60*1000
toString()
获取当前日期和时间并用以下形式的输出:dow mon dd hh:mm:ss zzz yyyy;dow是一周中的某一天
(Sun,Mon,Tue,Wed,Thu,Fri,Sat)
//public Date():分配一个Date对象,并初始化,以便他代表他被分配的时间,精确到毫秒
Date d1=new Date();
System.out.println(d1);
//public Date(long date):分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
long date=24*60*60*1000;
Date d2=new Date(date);
System.out.println(d2);
System.out.println(d2.toString());//输出:Fri Jan 02 08:00:00 CST 1970
2. DateFormat & SimpleDateFormat
a. DateFormat(抽象类)
此类是一个日期的格式化类,用来格式化日期。
具体日期可以通过java.util.Date类来获取。
DateFormat类的定义:此类是定义在java.test包中的。
public abstract class DateFormat extends Format
ⅰ. 实例化DateFormat
DateFormat是一个抽象类,按照以住的思路,直接使用其子类实例化即可。
但是DateFormat 类本身的内部提供了可以直接为其实例化的操作。
//得到日期的DateFormat对象:
public static final DateFormat getDateInstance();
//得到日期时间的DateFormat对象:
public static final DateFormat getDateTimeInstance();
//使用DateFormat类格式化Date类日期
public final String format(Date date)
ⅱ. 日期格式
1. 美式日期格式
import java.text.DateFormat ;
import java.util.Date ;
public class DateDemo03{
public static void main(String args[]){
DateFormat df1 = null ; // 声明一个DateFormat
DateFormat df2 = null ; // 声明一个DateFormat
df1 = DateFormat.getDateInstance() ; // 得到日期的DateFormat对象
df2 = DateFormat.getDateTimeInstance() ; // 得到日期时间的DateFormat对象
System.out.println("DATE:" + df1.format(new Date())) ; // 按照日期格式化
System.out.println("DATETIME:" + df2.format(new Date())) ; // 按照日期时间格式化
}
};
2. 中式日期格式
中式日期格式(通过Locale对象指定要显示的区域,指定的区域是中国)
import java.text.DateFormat ;
import java.util.Date ;
import java.util.Locale ;
public class DateDemo04{
public static void main(String args[]){
DateFormat df1 = null ; // 声明一个DateFormat
DateFormat df2 = null ; // 声明一个DateFormat
df1 = DateFormat.getDateInstance(DateFormat.YEAR_FIELD,new Locale("zh","CN")) ; // 得到日期的DateFormat对象
df2 = DateFormat.getDateTimeInstance(DateFormat.YEAR_FIELD,DateFormat.ERA_FIELD,new Locale("zh","CN")) ; // 得到日期时间的DateFormat对象
System.out.println("DATE:" + df1.format(new Date())) ; // 按照日期格式化
System.out.println("DATETIME:" + df2.format(new Date())) ; // 按照日期时间格式化
}
};
b. SimpleDateFormat类
SimpleDateFormat函数的继承关系:
java.lang.Object
|
+—-java.text.Format
|
+—-java.text.DateFormat
|
+—-java.text.SimpleDateFormat
将一种日期格式变为另外一种日期格式
原始日期:2008-10-19 10:11:30.345
转换后日期:2008 年 10 月 19 日 10 点 11 分 30 秒 345 毫秒
ⅰ. 日期模板
首先准备好一个日期格式模板,根据模板的格式来转化日期。
ⅱ. 使用
在构造对象时要传入日期格式模板
//构造方法:
public SimpleDateFormat(String pattern)
//转换:
public Date parse(String source)throws ParseException //-->此时取得的是全部时间数。
//格式化:
public final String Format(Date date) //-->将时间重新格式化成字符串显示。
ⅲ. 示例
把Date转化成指定的日期格式
public class FormatDateTime {
public static void main(String[] args) {
SimpleDateFormat myFmt=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
SimpleDateFormat myFmt1=new SimpleDateFormat("yy/MM/dd HH:mm");
SimpleDateFormat myFmt2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//等价于now.toLocaleString()
SimpleDateFormat myFmt3=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");
SimpleDateFormat myFmt4=new SimpleDateFormat(
"一年中的第 D 天 一年中第w个星期 一月中第W个星期 在一天中k时 z时区");
Date now=new Date();
System.out.println(myFmt.format(now));
System.out.println(myFmt1.format(now));
System.out.println(myFmt2.format(now));
System.out.println(myFmt3.format(now));
System.out.println(myFmt4.format(now));
System.out.println(now.toGMTString());
System.out.println(now.toLocaleString());
System.out.println(now.toString());
}
}
效果:
2023年12月16日 17时24分27秒
04/12/16 17:24
2023-12-16 17:24:27
2023年12月16日 17时24分27秒 星期四
一年中的第 351 天 一年中第51个星期 一月中第3个星期 在一天中17时 CST时区
16 Dec 2004 09:24:27 GMT
2023-12-16 17:24:27
Thu Dec 16 17:24:27 CST 2004
把给定的字符串中的日期提取为Date
这样做,通常是一个日期字符串,但不是想要的格式,可以先转化为Date,再转化为其它格式。
import java.text.* ;
import java.util.* ;
public class DateDemo05{
public static void main(String args[]){
String strDate = "2008-10-19 10:11:30.345" ;
// 准备第一个模板,从字符串中提取出日期数字
String pat1 = "yyyy-MM-dd HH:mm:ss.SSS" ;
// 准备第二个模板,将提取后的日期数字变为指定的格式
String pat2 = "yyyy年MM月dd日 HH时mm分ss秒SSS毫秒" ;
SimpleDateFormat sdf1 = new SimpleDateFormat(pat1) ; // 实例化模板对象
SimpleDateFormat sdf2 = new SimpleDateFormat(pat2) ; // 实例化模板对象
Date d = null ;
try{
d = sdf1.parse(strDate) ; // 将给定的字符串中的日期提取出来
}catch(Exception e){ // 如果提供的字符串格式有错误,则进行异常处理
e.printStackTrace() ; // 打印异常信息
}
System.out.println(sdf2.format(d)) ; // 将日期变为新的格式
}
};
c. DateFormat 和SimpleDateFormat 的区别
- DateFormat 可以直接使用,但其本身是一个抽象类,可以根据Locate指定的区域得到对应的日期时间格式
- SimpleDateFormat 类是DateFormat 类的子类,一般情况下来讲 DateFormat 类很少会直接使用。
而都使用SimpleDateFormat 类完成。
d. 演示示例
ⅰ. 使用Date类获取时间的信息
/**
目标:学会使用Date类处理时间,获取时间的信息
*/
public class DateDemo {
public static void main(String[] args) {
// 1、创建一个Date类的对象:代表系统此刻日期时间对象
Date d = new Date();
System.out.println(d);
// 2、获取时间毫秒值
long time = d.getTime();
System.out.println(time);
// long time1 = System.currentTimeMillis();
// System.out.println(time1);
System.out.println("----------------------------");
// 1、得到当前时间
Date d1 = new Date();
System.out.println(d1);
// 2、当前时间往后走 1小时 121s
long time2 = System.currentTimeMillis();
time2 += (60 * 60 + 121) * 1000;
// 3、把时间毫秒值转换成对应的日期对象。
// Date d2 = new Date(time2);
// System.out.println(d2);
Date d3 = new Date();
d3.setTime(time2);
System.out.println(d3);
}
}
ⅱ. SimpleDateFormat简单日期格式化类的使用
package com.zheng.d12_simpledateformat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
目标:SimpleDateFormat简单日期格式化类的使用
格式化时间
解析时间
*/
public class SimpleDateFormatDemo01 {
public static void main(String[] args) {
// 1、日期对象
Date d = new Date();
System.out.println(d);
// 2、格式化这个日期对象 (指定最终格式化的形式)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
// 3、开始格式化日期对象成为喜欢的字符串形式
String rs = sdf.format(d);
System.out.println(rs);
System.out.println("----------------------------");
// 4、格式化时间毫秒值
// 需求:请问121秒后的时间是多少
long time1 = System.currentTimeMillis() + 121 * 1000;
String rs2 = sdf.format(time1);
System.out.println(rs2);
System.out.println("------------解析字符串时间,下个代码---------------");
}
}
ⅲ. 使用SimpleDateFormat解析字符串时间成为日期对象
package com.zheng.d12_simpledateformat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo2 {
public static void main(String[] args) throws ParseException {
// 目标: 学会使用SimpleDateFormat解析字符串时间成为日期对象。
// 有一个时间 2021年08月06日 11:11:11 往后 2天 14小时 49分 06秒后的时间是多少。
// 1、把字符串时间拿到程序中来
String dateStr = "2021年08月06日 11:11:11";
// 2、把字符串时间解析成日期对象(本节的重点):形式必须与被解析时间的形式完全一样,否则运行时解析报错!
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = sdf.parse(dateStr);
// 3、往后走2天 14小时 49分 06秒
long time = d.getTime() + (2L*24*60*60 + 14*60*60 + 49*60 + 6) * 1000;
// 4、格式化这个时间毫秒值就是结果
System.out.println(sdf.format(time));
}
}
ⅳ. 秒杀案例
public class SimpleDateFormatTest3 {
public static void main(String[] args) throws ParseException {
// 1、开始 和 结束时间
String startTime = "2021-11-11 00:00:00";
String endTime = "2021-11-11 00:10:00";
// 2、小贾 小皮
String xiaoJia = "2021-11-11 00:03:47";
String xiaoPi = "2021-11-11 00:10:11";
// 3、解析他们的时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = sdf.parse(startTime);
Date d2 = sdf.parse(endTime);
Date d3 = sdf.parse(xiaoJia);
Date d4 = sdf.parse(xiaoPi);
if(d3.after(d1) && d3.before(d2)){
System.out.println("小贾秒杀成功,可以发货了!");
}else {
System.out.println("小贾秒杀失败!");
}
if(d4.after(d1) && d4.before(d2)){
System.out.println("小皮秒杀成功,可以发货了!");
}else {
System.out.println("小皮秒杀失败!");
}
}
}
ⅴ. String转换成Date对象
题目:请使用日期时间相关的API,计算出一个人已经出生了多少天。
思路:
① 获取当前时间对应的毫秒值
② 获取自己出生日期对应的毫秒值
③ 两个时间相减(当前时间– 出生日期)
代码实现:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/*
把String转换成Date对象
*/
public class Demo {
public static void main(String[] args) throws ParseException {
System.out.println("请输入出生日期 格式 YYYY-MM-dd");
// 获取出生日期,键盘输入
String birthdayString = new Scanner(System.in).next();
// 将字符串日期,转成Date对象
// 创建SimpleDateFormat对象,写日期模式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 调用方法parse,字符串转成日期对象
Date birthdayDate = sdf.parse(birthdayString);
// 获取今天的日期对象
Date todayDate = new Date();
// 将两个日期转成毫秒值,Date类的方法getTime
long birthdaySecond = birthdayDate.getTime();
long todaySecond = todayDate.getTime();
long secone = todaySecond-birthdaySecond;
if (secone < 0){
System.out.println("还没出生呢");
} else {
System.out.println(secone/1000/60/60/24);
}
}
}
请输入出生日期 格式 YYYY-MM-dd
2023-02-10
373
二、第二代日期类(Calendar)
1. 简介
java.util.Calendar是日历类,是一个抽象类,在Date后出现,替换掉了许多Date的方法。
该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的。
2. 演示示例
a. 日历类 Calendar
package com.zheng.d13_calendar;
import java.util.Calendar;
import java.util.Date;
/**
目标:日历类Calendar的使用,可以得到更加丰富的信息。
Calendar代表了系统此刻日期对应的日历对象。
Calendar是一个抽象类,不能直接创建对象。
Calendar日历类创建日历对象的语法:
Calendar rightNow = Calendar.getInstance();
Calendar的方法:
1.public static Calendar getInstance(): 返回一个日历类的对象。
2.public int get(int field):取日期中的某个字段信息。
3.public void set(int field,int value):修改日历的某个字段信息。
4.public void add(int field,int amount):为某个字段增加/减少指定的值
5.public final Date getTime(): 拿到此刻日期对象。
6.public long getTimeInMillis(): 拿到此刻时间毫秒值
小结:
记住。
*/
public class CalendarDemo{
public static void main(String[] args) {
// 1、拿到系统此刻日历对象
Calendar cal = Calendar.getInstance();
System.out.println(cal);
// 2、获取日历的信息:public int get(int field):取日期中的某个字段信息。
int year = cal.get(Calendar.YEAR);
System.out.println(year);
int mm = cal.get(Calendar.MONTH) + 1;
System.out.println(mm);
int days = cal.get(Calendar.DAY_OF_YEAR) ;
System.out.println(days);
// 3、public void set(int field,int value):修改日历的某个字段信息。
// cal.set(Calendar.HOUR , 12);
// System.out.println(cal);
// 4.public void add(int field,int amount):为某个字段增加/减少指定的值
// 请问64天后是什么时间
cal.add(Calendar.DAY_OF_YEAR , 64);
cal.add(Calendar.MINUTE , 59);
// 5.public final Date getTime(): 拿到此刻日期对象。
Date d = cal.getTime();
System.out.println(d);
// 6.public long getTimeInMillis(): 拿到此刻时间毫秒值
long time = cal.getTimeInMillis();
System.out.println(time);
}
}
结果:
java.util.GregorianCalendar[time=1693714170215,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2023,MONTH=8,WEEK_OF_YEAR=36,WEEK_OF_MONTH=2,DAY_OF_MONTH=3,DAY_OF_YEAR=246,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=9,SECOND=30,MILLISECOND=215,ZONE_OFFSET=28800000,DST_OFFSET=0]
2023
9
246
Mon Nov 06 13:08:30 CST 2023
1699247310215
三、第三代日期类(JDK8新特性)
1. 前面两代缺点
a. 设计很差
在 java.util 和 java.sql 的包中都有日期类,java.util.Date同时包含日期和时间,
而java.sql.Date仅包含日期,此外用于格式化和解析的类在java.text包中定义。
b. 非线程安全
java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
c. 时区处理麻烦
日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样
存在上述所有的问题。
2. 演示示例
package com.zheng.d7_newdatetimeapi;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo01 {
public static void main(String[] args) {
// 旧版日期时间 API 存在的问题
// 1.设计不合理
Date now = new Date(1985, 9, 23);
System.out.println(now);
// 2.时间格式化和解析是线程不安全的
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for (int i = 0; i < 50; i++) {
new Thread(() -> {
try {
Date date = sdf.parse("2023-08-09");
System.out.println("date = " + date);
} catch (ParseException e) {
e.printStackTrace();
}
}).start();
}
}
}
3. 新增日期时间 API
Java 8开始, java.time包下增加了一套全新的日期时间API,这套API设计合理,是线程安全的。
新的日期及时间API位于 java.time 包 中,下面是一些关键类。
- LocalDate:表示日期,包含年月日,格式为 2019-10-16
- LocalTime:表示时间,包含时分秒,格式为 16:38:54.158549300
- LocalDateTime:表示日期时间,包含年月日,时分秒,格式为 2018-09-06T15:33:56.750
- DateTimeFormatter:日期时间格式化类。
- Instant:时间戳,表示一个特定的时间瞬间。
- Duration:用于计算2个时间(LocalTime,时分秒)的距离
- Period:用于计算2个日期(LocalDate,年月日)的距离
- ZonedDateTime:包含时区的时间
Java中使用的历法是ISO 8601日历系统,它是世界民用历法,也就是我们所说的公历。
平年有365天,闰年是366天。
此外Java 8还提供了4套其他历法,分别是:
- ThaiBuddhistDate:泰国佛教历
- MinguoDate:中华民国历
- JapaneseDate:日本历
- HijrahDate:伊斯兰历
新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便,
其次, 新API的类型几乎全部是不可变类型(与String的使用类似),可放心使用而不必担心被修改
4. JDK 8的日期和时间类
a. LocalDate & LocalTime & LocalDateTime
LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、
时 间、日期和时间。
它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class ss {
// LocalDate:获取日期时间的信息。格式为 2019-10-16
@Test
public void test01() {
// 创建指定日期
LocalDate fj = LocalDate.of(1985, 9, 23);
System.out.println("fj = " + fj); // 1985-09-23
// 得到当前日期
LocalDate nowDate = LocalDate.now();
System.out.println("nowDate = " + nowDate); // 2019-10-16
// 获取日期信息
System.out.println("年: " + nowDate.getYear());
System.out.println("月: " + nowDate.getMonthValue());
System.out.println("日: " + nowDate.getDayOfMonth());
System.out.println("星期: " + nowDate.getDayOfWeek());
}
// LocalTime类: 获取时间信息。格式为 16:38:54.158549300
@Test
public void test02() {
// 得到指定的时间
LocalTime time = LocalTime.of(12,15, 28, 129_900_000);
System.out.println("time = " + time);
// 得到当前时间
LocalTime nowTime = LocalTime.now();
System.out.println("nowTime = " + nowTime);
// 获取时间信息
System.out.println("小时: " + nowTime.getHour());
System.out.println("分钟: " + nowTime.getMinute());
System.out.println("秒: " + nowTime.getSecond());
System.out.println("纳秒: " + nowTime.getNano());
}
// LocalDateTime类: 获取日期时间信息。格式为 2018-09-06T15:33:56.750
@Test
public void test03() {
LocalDateTime fj = LocalDateTime.of(1985, 9, 23, 9, 10, 20);
System.out.println("fj = " + fj); // 1985-09-23T09:10:20
// 得到当前日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now); // 2019-10-16T16:42:24.497896800
System.out.println(now.getYear());
System.out.println(now.getMonthValue());
System.out.println(now.getDayOfMonth());
System.out.println(now.getHour());
System.out.println(now.getMinute());
System.out.println(now.getSecond());
System.out.println(now.getNano());
}
}
结果:
fj = 1985-09-23T09:10:20
now = 2023-09-03T12:23:41.261714100
2023
9
3
12
23
41
261714100
ⅰ. 日期时间修改
对日期时间的修改,对已存在的LocalDate对象,创建它的修改版,最简单的方式是使用withAttribute方法。
withAttribute方法会创建对象的一个副本,并按照需要修改它的属性。
以下所有的方法都返回了一个修改属性的对 象,他们不会影响原来的对象。
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.LocalDateTime;
public class ss {
// LocalDateTime类: 对日期时间的修改
@Test
public void test05() {
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
// 修改日期时间
LocalDateTime setYear = now.withYear(2078);
System.out.println("修改年份: " + setYear);
System.out.println("now == setYear: " + (now == setYear));
System.out.println("修改月份: " + now.withMonth(6));
System.out.println("修改小时: " + now.withHour(9));
System.out.println("修改分钟: " + now.withMinute(11));
// 再当前对象的基础上加上或减去指定的时间
LocalDateTime localDateTime = now.plusDays(5);
System.out.println("5天后: " + localDateTime);
System.out.println("now == localDateTime: " + (now == localDateTime));
System.out.println("10年后: " + now.plusYears(10));
System.out.println("20月后: " + now.plusMonths(20));
System.out.println("20年前: " + now.minusYears(20));
System.out.println("5月前: " + now.minusMonths(5));
System.out.println("100天前: " + now.minusDays(100));
}
}
ⅱ. 日期时间的比较
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.LocalDate;
public class ss {
// 日期时间的比较
@Test
public void test06() {
// 在JDK8中,LocalDate类中使用isBefore()、isAfter()、equals()方法来比较两个日期,可直接进行比较。
LocalDate now = LocalDate.now();
LocalDate date = LocalDate.of(2018, 8, 8);
System.out.println(now.isBefore(date)); // false
System.out.println(now.isAfter(date)); // true
}
}
b. DateTimeFormatter(时间格式化与解析)
DateTimeFormatter:日期时间格式化类。
通过 java.time.format.DateTimeFormatter 类可以进行日期时间解析与格式化。
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ss {
// 日期格式化
@Test
public void test04() {
// 得到当前日期时间
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 将日期时间格式化为字符串
String format = now.format(formatter);
System.out.println("format = " + format);
// 将字符串解析为日期时间
LocalDateTime parse = LocalDateTime.parse("1985-09-23 10:12:22", formatter);
System.out.println("parse = " + parse);
}
}
c. Instant(时间戳)
Instant:时间戳,表示一个特定的时间瞬间,格式:2019-10-19T07:30:42.629520400Z
Instant 时间戳/时间线,内部保存了从1970年1月1日 00:00:00以来的秒和纳秒。
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.Instant;
public class ss {
// 时间戳
@Test
public void test07() {
Instant now = Instant.now();
System.out.println("当前时间戳 = " + now);
// 获取从1970年1月1日 00:00:00的秒
System.out.println(now.getNano());
System.out.println(now.getEpochSecond());
System.out.println(now.toEpochMilli());
System.out.println(System.currentTimeMillis());
Instant instant = Instant.ofEpochSecond(5);
System.out.println(instant);
}
}
d. Duration/Period(计算日期时间差类)
Duration/Period类: 计算日期时间差。
- Duration:用于计算2个时间(LocalTime,时分秒)的距离
- Period:用于计算2个日期(LocalDate,年月日)的距离
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.*;
public class ss {
// Duration/Period类: 计算日期时间差
@Test
public void test08() {
// Duration计算时间的距离
LocalTime now = LocalTime.now();
LocalTime time = LocalTime.of(14, 15, 20);
Duration duration = Duration.between(time, now);
System.out.println("相差的天数:" + duration.toDays());
System.out.println("相差的小时数:" + duration.toHours());
System.out.println("相差的分钟数:" + duration.toMinutes());
System.out.println("相差的秒数:" + duration.toSeconds());
// Period计算日期的距离
LocalDate nowDate = LocalDate.now();
LocalDate date = LocalDate.of(1998, 8, 8);
// 让后面的时间减去前面的时间
Period period = Period.between(date, nowDate);
System.out.println("相差的年:" + period.getYears());
System.out.println("相差的月:" + period.getMonths());
System.out.println("相差的天:" + period.getDays());
}
}
e. TemporalAdjuster & TemporalAdjusters(时间校正器)
有时我们可能需要获取例如:将日期调整到“下一个月的第一天”等操作。可以通过时间校正器来进行。
- TemporalAdjuster : 时间校正器
- TemporalAdjusters : 该类通过静态方法提供了大量的常用TemporalAdjuster的实现
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.*;
import java.time.temporal.TemporalAdjuster;
public class ss {
// TemporalAdjuster类:自定义调整时间
@Test
public void test09() {
LocalDateTime now = LocalDateTime.now();
// 得到下一个月的第一天
TemporalAdjuster firsWeekDayOfNextMonth = temporal -> {
LocalDateTime dateTime = (LocalDateTime) temporal;
LocalDateTime nextMonth = dateTime.plusMonths(1).withDayOfMonth(1);
System.out.println("nextMonth = " + nextMonth);
return nextMonth;
};
LocalDateTime nextMonth = now.with(firsWeekDayOfNextMonth);
System.out.println("nextMonth = " + nextMonth);
}
}
f. 设置日期时间的时区
Java8 中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime是不带时区的,
带时区的日期时间类分别 为:ZonedDate、ZonedTime、ZonedDateTime。
其中每个时区都对应着 ID,ID的格式为 “区域/城市” 。
例如 :Asia/Shanghai 等。ZoneId:该类中包含了所有的时区信息。
package com.zheng.d7_newdatetimeapi;
import org.junit.Test;
import java.time.*;
public class ss {
// 设置日期时间的时区
@Test
public void test10() {
// 1.获取所有的时区ID
// ZoneId.getAvailableZoneIds().forEach(System.out::println);
// 不带时间,获取计算机的当前时间
LocalDateTime now = LocalDateTime.now(); // 中国使用的东八区的时区.比标准时间早8个小时
System.out.println("now = " + now);
// 2.操作带时区的类
// now(Clock.systemUTC()): 创建世界标准时间
ZonedDateTime bz = ZonedDateTime.now(Clock.systemUTC());
System.out.println("bz = " + bz);
// now(): 使用计算机的默认的时区,创建日期时间
ZonedDateTime now1 = ZonedDateTime.now();
System.out.println("now1 = " + now1); // 2019-10-19T16:19:44.007153500+08:00[Asia/Shanghai]
// 使用指定的时区创建日期时间
ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("America/Vancouver"));
System.out.println("now2 = " + now2); // 2019-10-19T01:21:44.248794200-07:00[America/Vancouver]
}
}
g. 总结
新的日期是时间相关类:
- LocalDate表示日期,包含年月日,LocalTime表示时间,包含时分 秒,LocalDateTime = LocalDate + LocalTime,
- 时间的格式化和解析,通过DateTimeFormatter类型进行.
- Instant类,方便操作秒和纳秒,一般是给程序使用的
- Duration/Period计算日期或时间的距离,还使用时间调 整器方便的调整时间,
- 带时区的3个类ZoneDate/ZoneTime/ZoneDateTime
JDK 8新的日期和时间 API的优势:
- 新版的日期和时间API中,日期和时间对象是不可变的。操纵的日期不会影响老值,而是新生成一个实例。
- 新的API提供了两种不同的时间表示方式,有效地区分了人和机器的不同需求。
- TemporalAdjuster可以更精确的操纵日期,还可以自定义日期调整器。
- 是线程安全的