一、JDK8之前的API:
-
System类的currentTimeMillis()
获取当前时间对应的毫秒数,long类型,时间戳
当前时间与1970年1月1日0时0分0秒之间的毫秒数
常用来计算时间差 -
两个Date类
|–java.util.Date两个构造器的使
两个方法的使用:①toString() ② long getTime()
|----java.sql.Date: 对应着数据库中的date类型
Date date1 = new Date(); //创建一个基于当前系统时间的Date的实例
System.out.println(date1.toString());//Mon Dec 05 11:56:26 CST 2022
long milliTimes = date1.getTime();
System.out.println("对应的毫秒数为:" + milliTimes); //1670212256045
Date date2 = new Date(1370202256045L); //创建一个基于指定时间戳的Date的实例
System.out.println(date2.toString());
-
SimpleDateFormat类
SimpleDateFormat类:用于日期时间的格式化和解析格式化:日期—>字符串
解析:字符串 —> 日期SimpleDateFormat sdf = new SimpleDateFormat(); //格式化:日期--->字符串 Date date1 = new Date(); String strDate = sdf.format(date1); System.out.println(strDate);//22-12-5 下午2:21 //解析:字符串 ---> 日期 Date date2 = sdf.parse("22-12-5 下午3:21"); System.out.println(date2); SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //格式化:日期--->字符串 Date date1 = new Date(); String strDate = sdf.format(date1); System.out.println(strDate);//2022-12-05 14:27:19 //解析:字符串 ---> 日期 Date date2 = sdf.parse("2022-12-05 14:27:19"); System.out.println(date2); //解析失败。因为参数的字符串不满足SimpleDateFormat可以识别的格式。 // Date date3 = sdf.parse("22-12-5 下午2:21"); // System.out.println(date2);
-
Calendar类(日历类):抽象类
Calendar:日历类
① 实例化 由于Calendar是一个抽象类,所以我们需要创建其子类的实例。这里我们通过Calendar的静态方法
getInstance()即可获取②常用方法:get(int field) / set(int field,xx) / add(int field,xx) / getTime() / setTime()
calendar面临的问题是:
-
可变性:像日期和时间这样的类应该是不可变的。
-
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
-
格式化:格式化只对Date有用,Calendar则不行。
-
此外,它们也不是线程安全的;不能处理闰秒等。
闰秒,是指为保持协调世界时接近于世界时时刻,由国际计量局统一规定在年底或年中(也可能在季末)对协调世界时增加或减少1秒的调整。由于地球自转的不均匀性和长期变慢性(主要由潮汐摩擦引起的),会使世界时(民用时)和原子时之间相差超过到±0.9秒时,就把协调世界时向前拨1秒(负闰秒,最后一分钟为59秒)或向后拨1秒(正闰秒,最后一分钟为61秒); 闰秒一般加在公历年末或公历六月末。
目前,全球已经进行了27次闰秒,均为正闰秒。
总结:
对日期和时间的操作一直是Java程序员最痛苦的地方之一
。 -
Calendar calendar = Calendar.getInstance();
// System.out.println(calendar.getClass());
//测试方法
//get(int field)
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//set(int field,xx)
calendar.set(Calendar.DAY_OF_MONTH,23);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
//add(int field,xx)
calendar.add(Calendar.DAY_OF_MONTH,3);
calendar.add(Calendar.DAY_OF_MONTH,-5);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
//getTime():Calender --> Date
Date date = calendar.getTime();
System.out.println(date);
//setTime():使用指定Date重置Calendar
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
如何将一个java.util.Date的实例转换为java.sql.Date的实例
拓展:
将控制台获取的年月日(比如:2022-12-13)的字符串数据,保存在数据库中。
(简化为得到java.sql.Date的对象,此对象对应的时间为2022-12-13)。
/*
* 练习:
如何将一个java.util.Date的实例转换为java.sql.Date的实例
* */
@Test
public void test1(){
Date date1 = new Date();
//错误的:
// java.sql.Date date2 = (java.sql.Date) date1;
// System.out.println(date2);
//正确的:
java.sql.Date date2 = new java.sql.Date(date1.getTime());
System.out.println(date2);
}
/*
* 拓展:
将控制台获取的年月日(比如:2022-12-13)的字符串数据,保存在数据库中。
(简化为得到java.sql.Date的对象,此对象对应的时间为2022-12-13)。
*
* 字符串 ---> java.util.Date ---> java.sql.Date
* */
@Test
public void test2() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String pattern = "2022-12-13";
//得到java.util.Date
Date date1 = sdf.parse(pattern);
//转换为java.sql.Date
java.sql.Date date2 = new java.sql.Date(date1.getTime());
System.out.println(date2);
}
二、JDK8中的API:
- LocalDate,LocalTime,LocalDateTime —>类似于Calendar
实例化:now() / of(xxx,xx,xx)
方法:get() / withXxx() / plusXxx() / minusXxx()
//now():获取当前日期和时间对应的实例
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);//2022-12-05
System.out.println(localTime);//15:43:51.474
System.out.println(localDateTime); //2022-12-05T15:43:51.475
//of():获取指定的日期、时间对应的实例
LocalDate localDate1 = LocalDate.of(2021, 5, 23);
LocalDateTime localDateTime1 = LocalDateTime.of(2022, 12, 5, 11, 23, 45);
System.out.println(localDate1);
System.out.println(localDateTime1);
//getXXX()
LocalDateTime localDateTime2 = LocalDateTime.now();
System.out.println(localDateTime2.getDayOfMonth());
//体现不可变性
//withXxx()
LocalDateTime localDateTime3 = localDateTime2.withDayOfMonth(15);
System.out.println(localDateTime2);//2022-12-05T15:48:48.399
System.out.println(localDateTime3);//2022-12-15T15:48:48.399
//plusXxx()
LocalDateTime localDateTime4 = localDateTime2.plusDays(5);
System.out.println(localDateTime2);//2022-12-05T15:50:21.864
System.out.println(localDateTime4);//2022-12-10T15:50:21.864
-
Instant:瞬时 —>类似于Date
Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
- 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
java.time.Instant
表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。
方法 描述 now()
静态方法,返回默认UTC时区的Instant类的对象 ofEpochMilli(long epochMilli)
静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象 atOffset(ZoneOffset offset) 结合即时的偏移来创建一个 OffsetDateTime toEpochMilli()
返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳 中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。
instant.atOffset(ZoneOffset.ofHours(8));
实例化:now() / ofEpochMilli()
方法:toEpochMilli()
DateTimeFormatter该类提供了三种格式化方法:
-
(了解)预定义的标准格式。如:ISO_LOCAL_DATE_TIME、ISO_LOCAL_DATE、ISO_LOCAL_TIME
-
(了解)本地化相关的格式。如:ofLocalizedDate(FormatStyle.LONG)
// 本地化相关的格式。如:ofLocalizedDateTime() // FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime // 本地化相关的格式。如:ofLocalizedDate() // FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
-
自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
方 法 | 描 述 |
---|---|
ofPattern(String pattern) | 静态方法,返回一个指定字符串格式的DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、时间 |
//now():
Instant instant = Instant.now();
System.out.println(instant);//2022-12-05T07:56:27.327Z
//了解:
OffsetDateTime instant1 = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(instant1);//2022-12-05T15:56:27.327+08:00
Instant instant2 = Instant.ofEpochMilli(24123123312L);
System.out.println(instant2); //1970-10-07T04:52:03.312Z
long milliTime = instant.toEpochMilli();
System.out.println(milliTime);
System.out.println(new Date().getTime());
DateTimeFormatter ---> 类似于SimpleDateFormat
用于格式化和解析LocalDate,LocalTime,LocalDateTime
//自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//格式化:日期、时间-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String strDateTime = dateTimeFormatter.format(localDateTime);
System.out.println(strDateTime);//2022/12/05 16:04:44
//解析:字符串 ---> 日期、时间
TemporalAccessor temporalAccessor = dateTimeFormatter.parse("2022/12/05 15:04:44");
LocalDateTime localDateTime1 = LocalDateTime.from(temporalAccessor);
System.out.println(localDateTime1);//2022-12-05T15:04:44
//ctrl + alt 显示类的关系图
指定时区日期时间:ZondId和ZonedDateTime
-
ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris
-
ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12-03T10:15:30+01:00 Europe/Paris。
- 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等
-
常见时区ID:
Asia/Shanghai
UTC
America/New_York
- 可以通过ZondId获取所有可用的时区ID:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
public class TestZone {
@Test
public void test01() {
//需要知道一些时区的id
//Set<String>是一个集合,容器
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
//快捷模板iter
for (String availableZoneId : availableZoneIds) {
System.out.println(availableZoneId);
}
}
@Test
public void test02(){
ZonedDateTime t1 = ZonedDateTime.now();
System.out.println(t1);
ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(t2);
}
}
持续日期/时间:Period和Duration
- 持续时间:Duration,用于计算两个“时间”间隔
- 日期间隔:Period,用于计算两个“日期”间隔
import org.junit.Test;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class TestPeriodDuration {
@Test
public void test01(){
LocalDate t1 = LocalDate.now();
LocalDate t2 = LocalDate.of(2018, 12, 31);
Period between = Period.between(t1, t2);
System.out.println(between);
System.out.println("相差的年数:"+between.getYears());
System.out.println("相差的月数:"+between.getMonths());
System.out.println("相差的天数:"+between.getDays());
System.out.println("相差的总数:"+between.toTotalMonths());
}
@Test
public void test02(){
LocalDateTime t1 = LocalDateTime.now();
LocalDateTime t2 = LocalDateTime.of(2017, 8, 29, 0, 0, 0, 0);
Duration between = Duration.between(t1, t2);
System.out.println(between);
System.out.println("相差的总天数:"+between.toDays());
System.out.println("相差的总小时数:"+between.toHours());
System.out.println("相差的总分钟数:"+between.toMinutes());
System.out.println("相差的总秒数:"+between.getSeconds());
System.out.println("相差的总毫秒数:"+between.toMillis());
System.out.println("相差的总纳秒数:"+between.toNanos());
System.out.println("不够一秒的纳秒数:"+between.getNano());
}
@Test
public void test03(){
//Duration:用于计算两个“时间”间隔,以秒和纳秒为基准
LocalTime localTime = LocalTime.now();
LocalTime localTime1 = LocalTime.of(15, 23, 32);
//between():静态方法,返回Duration对象,表示两个时间的间隔
Duration duration = Duration.between(localTime1, localTime);
System.out.println(duration);
System.out.println(duration.getSeconds());
System.out.println(duration.getNano());
LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
Duration duration1 = Duration.between(localDateTime1, localDateTime);
System.out.println(duration1.toDays());
}
}
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。
@Test
public void test1(){
// TemporalAdjuster:时间校正器
// 获取当前日期的下一个周日是哪天?
TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
System.out.println(localDateTime);
// 获取下一个工作日是哪天?
LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = (LocalDate) temporal;
if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
return date.plusDays(3);
} else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
return date.plusDays(2);
} else {
return date.plusDays(1);
}
}
});
System.out.println("下一个工作日是:" + localDate);
/**
*2024-05-19T11:00:51.039147
*下一个工作日是:2024-05-17
}
自己的测试代码
public class DateParse {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String format = simpleDateFormat.format(date);
System.out.println(format);
Calendar instance = Calendar.getInstance();
System.out.println(instance);
String calendarType = instance.getCalendarType();
System.out.println(calendarType);
/**
* Thu May 16 09:40:02 CST 2024
* 2024-05-16
* java.util.GregorianCalendar[time=1715823602121,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=2024,MONTH=4,WEEK_OF_YEAR=20,WEEK_OF_MONTH=3,DAY_OF_MONTH=16,DAY_OF_YEAR=137,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=9,HOUR_OF_DAY=9,MINUTE=40,SECOND=2,MILLISECOND=121,ZONE_OFFSET=28800000,DST_OFFSET=0]
* gregory 格里高利历或公历 所以为啥十月革命在1917年十一月发生,这个“十月”是儒略历的十月,“十一月”是格里历的十一月 俄罗斯直到1918年才承认格里历
*/
System.out.println("-------------------------");
Date date1 = new Date(1715758583857L);
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(date1);
System.out.println(simpleDateFormat.format(date1));
System.out.println(simpleDateFormat1.format(date1));
Date parse = null;
try {
parse = simpleDateFormat1.parse("2024-05-25 15:36:23");
} catch (ParseException e) {
throw new RuntimeException(e);
}
System.out.println(parse);
/**
* Wed May 15 15:36:23 CST 2024
* 2024-05-15
* 2024-05-15 15:36:23
* Sat May 25 15:36:23 CST 2024
*/
System.out.println("-----------------");
Date time = instance.getTime();
System.out.println(time);
int day = instance.get(Calendar.DAY_OF_YEAR);
int monthDay = instance.get(Calendar.DAY_OF_MONTH);
int month = instance.get(Calendar.MONTH);
int year = instance.get(Calendar.YEAR);
System.out.println("一年中的第" + day + "天");
System.out.println("monthDay:" + monthDay);
System.out.println("month:" + month);
System.out.println("year:" + year);
/**
* Thu May 16 10:07:18 CST 2024
* 一年中的第137天
* monthDay:16
* month:4(月份从0开始)
*/
System.out.println("-------------");
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
/**
* 2024-05-16
* 10:10:26.960086400
* 2024-05-16T10:10:26.960086400
*/
System.out.println("-------------------------");
instance.add(Calendar.DAY_OF_MONTH,10);
System.out.println(instance.getTime());
LocalDate localDate1 = localDate.withDayOfMonth(25);
System.out.println("localDate:" + localDate);
System.out.println("localDate1:" + localDate1);
/**
* Calender会改变原有日期变量,增加了10天
* Sun May 26 10:15:24 CST 2024
* 不变性
* localDate:2024-05-16
* localDate1:2024-05-25
*/
System.out.println("---------------------");
Instant now = Instant.now();
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
System.out.println(now);
Instant instant = Instant.ofEpochMilli(1715758583857L);
System.out.println(instant);
OffsetDateTime offsetDateTime1 = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime1);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(dateTimeFormatter.format(localTime));
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("");
System.out.println(dateTimeFormatter1.format(localTime));
/**
* 默认不是东8区,是中时区时间
* 2024-05-16T10:25:19.906403700+08:00
* 2024-05-16T02:25:19.906403700Z
* 2024-05-15T07:36:23.857Z
* 2024-05-15T15:36:23.857+08:00
* patten出错,"yyyy-MM-dd HH:mm:ss" Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
* 10:30:57
* 解析不了输出空字符串
*/
System.out.println("-----------------------");
// TemporalAdjuster:时间校正器
// 获取当前日期的下一个周日是哪天?
TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
LocalDateTime localDateTime3 = LocalDateTime.now().with(temporalAdjuster);
System.out.println(localDateTime3);
// 获取下一个工作日是哪天?
LocalDate localDate3 = LocalDate.now().with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = (LocalDate) temporal;
if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
return date.plusDays(3);
} else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
return date.plusDays(2);
} else {
return date.plusDays(1);
}
}
});
System.out.println("下一个工作日是:" + localDate3);
}
}
/**
* 2024-05-19T11:00:51.039147
* 下一个工作日是:2024-05-17
*/
本文参考了尚硅谷宋红康老师的讲义