日期时间类
- 一、JDK8之前日期时间
- 二、JDK8中日期时间
一、JDK8之前日期时间
1. 获取时间:System.currentTimeMillis()
关于计算时间的标准可参考https://baijiahao.baidu.com/s?id=1732139602203523267&wfr=spider&for=pc我国处于东八区,与中时区时差为8小时,也就是UTC+8。
2. 获取日期:java.util.Date
// java.util.Date
// 1.无参构造 获取本地当前时间戳 以特定格式表示
Date date1 = new Date();
System.out.println(date1);// Fri Mar 24 14:07:18 CST 2023
// System.out.println(date1.toString());
long time = date1.getTime(); // 获取当前日期时间对应的时间戳,单位ms
System.out.println(time); // 1679638038632
// 2.有参构造
Date date2=new Date(time); // 将输入的表示时间戳的time转换为特定格式输出
System.out.println(date2);// Fri Mar 24 14:07:18 CST 2023
System.out.println(date2.getTime()); // 1679638038632
2.1. 获取日期:java.sql.Date
- 继承于java.util.Date,专门用于表示数据库语言SQL中的日期类型;
- 仅有有参构造,输入为表示时间戳(单位ms)的long型整数,构造以特定格式表示时间的Date对象;
// java.sql.Date
java.sql.Date date = new java.sql.Date(1679638038632L);
System.out.println(date); // 2023-03-24
System.out.println(date.toString()); // 2023-03-24
System.out.println(date.getTime()); // 1679638038632
2.2.两种日期类的转换:
// java.sql.Date->java.util.Date 子类到父类,直接赋值即可
// java.util.Date-> java.sql.Date 父类转子类
// 情况1,最初实际声明的还是子类对象,直接强制转换即可
// Date date=new java.sql.Date(1679638038632L);
// java.sql.Date date1=(java.sql.Date)date;
// System.out.println(date); // 2023-03-24
// System.out.println(date1); // 2023-03-24
// 情况2,最初实际声明的是父类对象,无法直接强制转换
// 可先通过Date对象的getTime()方法获取时间戳,然后实例化java.sql.Date即可
Date date=new Date(1679638038632L);
java.sql.Date date1 = new java.sql.Date(date.getTime());
System.out.println(date); // Fri Mar 24 14:07:18 CST 2023
System.out.println(date1); // 2023-03-24
3. 获取格式化日期:java.text.SimpleDateFormat
继承自java.text.DateFormat,可对日期类Date对象进行指定形式的格式化,或者对满足指定格式的字符串解析为Date对象。
- 使用无参构造new SimpleDateFormat()进行实例化后,则在对Date对象进行格式化或对字符串进行解析时,会使用默认的格式;
- 如果想指定日期时间的格式,需要通过使用有参构造new SimpleDateFormat(String pattern)中的参数pattern进行指定,关于pattern的指定可参考官方文档,其中使用的字符含义如下:
@Test
public void formatDemo() throws Exception{
// 测试java.text.SimpleDateFormat
SimpleDateFormat format = new SimpleDateFormat("yyyy+MM+dd - hh:mm:ss");
Date date = new Date();
System.out.println(date); // Fri Mar 24 21:44:41 CST 2023
// 格式化操作
String formattedDate = format.format(date); // 2023+03+24 - 09:44:41
System.out.println(formattedDate);
// 解析操作
String dateStr="2023+03+24 - 09:44:41";
Date parsedDate = format.parse(dateStr);
System.out.println(parsedDate);
}
3.1 相关练习
练习1:将表示时间的字符串Str转换为java.sql.Date对象
- 1.java.sql.Date只可通过有参构造实例化;
- 2.字符串可通过java.text.SimpleDateFormat的parse方法解析为java.util.Date对象;
- 3.java.util.Date可转换为java.sql.Date对象;
练习2:“三天打渔两日晒网”,从1990-01-01为基准,随机指定一个日期某年某月某日,问这一天是在打渔还是晒网?
- 1.“三天打渔两日晒网”流程以5天为一个完整周期,其中距离基准为0,1,2天的时间为打渔,距离为3,4的为晒网,比如1990-01-02距离基准1990-01-01为1天,则这天在打渔;
- 2.思路:确定指定日期距离基准日期的天数,然后对周期5进行取余,其中距离基准为0,1,2天的时间为打渔,距离为3,4的为晒网;计算天数的方法有两种:1)计算指定日期的时间戳与基准时间戳的差值,该差值表示二者之间距离的毫秒数,将其转化为天数即可;2)直接对二者之间的天数进行计数,其中涉及闰年判断,整年计数、整月计数等,可借助java.util.Calendar日历类实现;
package com.northsmile.dateandtime;
import lombok.SneakyThrows;
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
/**
* Author:NorthSmile
* Date:2023/3/25 8:40
* JDK8之前日期时间类例题
*/
public class Example {
// **练习1:将表示时间的字符串Str转换为java.sql.Date对象**
//
// - 1.java.sql.Date只可通过有参构造实例化;
// - 2.字符串可通过java.text.SimpleFormat的parse方法解析为java.util.Date对象;
// - 3.java.util.Date可转换为java.sql.Date对象;
@SneakyThrows
@Test
public void strToSqlDate(){
String dateStr="2020-09-08 12:02:03";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// str->java.util.Date
Date date = dateFormat.parse(dateStr);
System.out.println(date);
// java.util.Date->java.sql.Date
java.sql.Date resDate = new java.sql.Date(date.getTime());
System.out.println(resDate);
}
// **练习2:“三天打渔两日晒网”,从1990-01-01为基准,随机指定一个日期某年某月某日,问这一天是在打渔还是晒网?**
//
// - 1.“三天打渔两日晒网”流程以5天为一个完整周期,其中距离基准为0,1,2天的时间为打渔,距离为3,4的为晒网,比如1990-01-02距离基准1990-01-01为1天,则这天在打渔;
// - 2.思路:确定指定日期距离基准日期的天数,然后对周期5进行取余,其中距离基准为0,1,2天的时间为打渔,距离为3,4的为晒网;计算天数的方法有两种:1)计算指定日期的时间戳与基准时间戳的差值,该差值表示二者之间距离的毫秒数,将其转化为天数即可;
// 2)直接对二者之间的天数进行计数,其中涉及闰年判断,整年计数、整月计数等,可借助java.util.Calendar日历类实现;
@SneakyThrows
public static void dateDiff(String curDate){
System.out.println(curDate);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String base="1990-01-01";
// 方法一:使用时间戳
// long baseTime=dateFormat.parse(base).getTime();
// // 解析字符串
// long curTime = dateFormat.parse(curDate).getTime();
// long days = (curTime - baseTime) / (1000 * 60 * 60*24); // 计算时差,并转换为天数
// 方法二:将时间差分为三部分,1)基准年总天数-基准日期距离年初的天数;2)中间的完整年份;3)当前日期距离年初的天数;
// 借助Calendar日历类实现
Calendar calendar = Calendar.getInstance();
// 1)基准年总天数-基准日期距离年初的天数;
calendar.setTime(dateFormat.parse(base));
int baseYear = calendar.get(Calendar.YEAR);
int days=365-calendar.get(Calendar.DAY_OF_YEAR);
days+=(isLeapYear(baseYear)?1:0);
calendar.setTime(dateFormat.parse(curDate));
int curYear = calendar.get(Calendar.YEAR); // 当前年
// 2)中间的完整年份;
days+=((curYear-1-baseYear)*365);
for (int year=baseYear+1;year<curYear;year++){
if (isLeapYear(year)){
days++;
}
}
// 3)当前日期距离年初的天数;
days+=(calendar.get(Calendar.DAY_OF_YEAR));
System.out.println(days);
long sign=days%5;
if (sign<3){
System.out.println(curDate+"在打渔");
}else{
System.out.println(curDate+"在晒网");
}
}
// 判断是否为闰年
private static boolean isLeapYear(int year) {
if (year%400==0||(year%4==0&&year%100!=0)){
return true;
}
return false;
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请按照yyyy-mm-dd格式输入需查询的日期:");
while (scanner.hasNext()){
String curDate = scanner.nextLine();
dateDiff(curDate);
System.out.println("请按照yyyy-mm-dd格式输入需查询的日期:");
}
}
}
4. 日历类:java.util.Calendar
- 该类为抽象类,无法直接进行实例化,其实例化方式有两种:1)使用子类构造器GregorianCalendar;2).调用静态方法getInstance()即可;
- 默认表示系统当前日历时间,可对该时间进行修改设置;
- Calendar的属性有两个需要注意:DAY_OF_WEEK_IN_MONTH和WEEK_OF_MONTH,他们都表示当前月第几周,区别在于:
WEEK_OF_MONTH参考标准为日历时间,当天在公历中当月属于第几周就是多少,以周日为起点,周六表示一周结束;DAY_OF_WEEK_IN_MONTH参考标准为当月总天数,以当前月第一天为第一周的第一天,如此计算;比如2023.3.26,对于WEEK_OF_MONTH来说属于第5周(3.1-3.4属于第一周,5号是新的一周开始),而DAY_OF_WEEK_IN_MONTH为第4周(3*7+5=26);
public static void main(String[] args) {
// 实例化方式:
// 1.使用子类构造器
// Calendar calendar=new GregorianCalendar();
// 2.调用静态方法getInstance()
Calendar ca = Calendar.getInstance();
// System.out.println(calendar);
// 1)获取日期相关属性值
// 年月日
// System.out.println(ca.get(Calendar.YEAR));
// System.out.println(ca.get(Calendar.MONTH)+1); // 1-12月使用0-11表示
// System.out.println(ca.get(Calendar.DATE));
// System.out.println(ca.get(Calendar.DAY_OF_YEAR)); // 该年第几天
// System.out.println(ca.get(Calendar.DAY_OF_MONTH)); // 该月第几天
// System.out.println(ca.get(Calendar.DAY_OF_WEEK)); // 该周第几天 周日-周六使用1-7表示
// ca.add(Calendar.DATE,-24);
// System.out.println(ca.get(Calendar.DATE));
// System.out.println(ca.get(Calendar.DAY_OF_WEEK)); // 该周第几天 周日-周六使用1-7表示
// System.out.println(ca.get(Calendar.DAY_OF_WEEK_IN_MONTH)); // 视当月第一天为周日,表示当前月当天属于第几周,以当前月天数进行计算
// System.out.println(ca.get(Calendar.WEEK_OF_MONTH)); //当月第几周 以周日为一周的开始
// System.out.println(ca.get(Calendar.WEEK_OF_YEAR)); // 当年第几周
// 时分秒
// System.out.println(ca.get(Calendar.HOUR_OF_DAY)); // 一天的第几个小时
// System.out.println(ca.get(Calendar.HOUR));
// System.out.println(ca.get(Calendar.MINUTE));
// System.out.println(ca.get(Calendar.SECOND));
// 2)设置日期相关属性值
ca.set(Calendar.DATE,1);
System.out.println(ca.get(Calendar.DATE));
// 3)修改日期相关属性值
ca.add(Calendar.DATE,-1);
System.out.println(ca.get(Calendar.DATE));
System.out.println(ca.get(Calendar.MONTH));
// java.util.Date与java.util.Calendar互相转换
// java.util.Date->java.util.Calendar
// Date base=new Date();
// System.out.println(base);
// ca.setTime(base;
// // java.util.Calendar-->java.util.Date
// Date time = ca.getTime();
// System.out.println(time);
}
二、JDK8中日期时间
JDK8之前的日期时间类存在一些问题,新的API可解决这些问题:
Joda-Time是一个第三方库,可解决之前日期时间类的问题,JDK8时借鉴Joda-Time实现了新的API。在使用JDK8以前API时,可添加Joda-Time对应jar包使用其提供的良好性能的日期时间API。
java.time.LocalDate/java.time.LocalDateTime/java.time.LocalTime:
这一系列类可近似为java.util.Calendar类处理:
瞬时:java.time.Instant
该类可近似为java.util.Date类处理:
日期时间格式化:java.time.format.DateTimeFormatter:
类似于java.text.SimpleDateFormat处理:
格式化方式有以下三种,常用方式为自定义格式化。
package com.northsmile.dateandtime;
import org.junit.Test;
import javax.print.attribute.standard.DateTimeAtCompleted;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
/**
* @author NorthSmile
* @version 1.0
* @date 2023/3/26&15:46
* LocalDate/LocalDateTime/LocalTime/Instant/DateTimeFormatter测试
*/
public class LocalAndInstantDemo {
@Test
public void localDemo(){
// 获取实例:本地日期、时间(默认格式显示)
// LocalDate localDate = LocalDate.now();
// System.out.println(localDate);
// LocalTime localTime = LocalTime.now();
// System.out.println(localTime);
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
// 指定日期时间创建对应实例
// LocalDateTime localDateTime2 = LocalDateTime.of(2023, 3, 27, 13, 45, 56);
// System.out.println(localDateTime2);
// 获取指定时区日期时间
LocalDateTime dateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
LocalDateTime dateTime1 = LocalDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(dateTime);
System.out.println(dateTime1);
// 获取localDateTime的属性信息
// 年月
// System.out.println(localDateTime.getYear());
// System.out.println(localDateTime.getMonth()+":"+localDateTime.getMonthValue());
//
// System.out.println(localDateTime.getDayOfYear()); // 当年第多少天
// System.out.println(localDateTime.getDayOfMonth()); // 当月第多少天
//
// System.out.println(localDateTime.getDayOfWeek()); // 星期几
//
// // 时分秒
// System.out.println(localDateTime.getHour());
// System.out.println(localDateTime.getMinute());
// System.out.println(localDateTime.getSecond());
// 设置localDateTime的属性信息
// LocalDateTime localDateTime1 = localDateTime.withDayOfMonth(4); // 创建新的对象,原对象内容不变
// System.out.println(localDateTime);
// System.out.println(localDateTime1);
// 修改localDateTime的属性信息
// LocalDateTime localDateTime1 = localDateTime.plusYears(1);
// System.out.println(localDateTime1);
// LocalDateTime localDateTime2 = localDateTime.minusYears(1);
// System.out.println(localDateTime2);
}
@Test
public void instantDemo(){
// 获取默认UTC时区日期时间:为国内时间减去8小时对应时间
Instant now = Instant.now();
System.out.println(now);
// 根据时差偏移创建OffsetDateTime对象
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
// 获取时间戳
System.out.println(now.toEpochMilli());
// 根据指定时间戳实例化对虾干
Instant now1 = Instant.ofEpochMilli(now.toEpochMilli());
System.out.println(now1);
}
@Test
public void formatDemo(){
// 实例化格式化对象
// 方式一:
DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ISO_TIME;
// System.out.println(dateTimeFormatter2);
System.out.println(dateTimeFormatter2.format(LocalTime.now()));
// DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
// System.out.println(dateTimeFormatter1);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd & HH:mm:ss");
// System.out.println(dateTimeFormatter);
// 格式化操作
String str = dateTimeFormatter.format(LocalDateTime.now());
System.out.println(str);
// 解析操作
TemporalAccessor date = dateTimeFormatter.parse(str);
System.out.println(date);
}
}
其他日期时间API:
JDK8前后日期时间API之间的转换: