java常用时间日期类总结
前置知识:
UTC时间(Coordinated Universal Time):协调世界时,主要的世界时间标准,0时区的时间
UTC+8:东八区时间
Epoch(纪元):1970-01-01 00:00:00 UTC(北京时间1970-01-01 00:08:00 UTC+8)
常用类 |
描述 |
|
---|---|---|
System.currentTimeMillis() |
返回Epoch至今的毫秒数 |
|
java.util.Date |
表示一个时刻,记录Epoch到该时刻的UTC时间相差的毫秒数(其中多数方法已废弃) |
|
java.util.Calendar |
抽象类,提供了以年,月,日,时分秒,星期等为单位操作的方法 |
|
java.text.SimpleDateFormat |
将时间格式化为字符串,将字符串解析为时间 |
|
java.util.TimeZone |
时区 |
|
java.time.Instant |
表示时刻,精确到nanos,提供了计算的方法 |
jdk8 |
java.time.LocalDate |
没有时区信息的时间/日期/时间日期 并不能表示某个时刻 |
|
java.time.LocalTime |
||
java.time.LocalDateTime |
||
java.time.ZonedDateTime |
有时区的时间日期 |
|
java.time.format.DateTimeFormatter |
时间格式化 |
|
java.time.Duration |
一段时间,基于秒和纳秒,例如:32秒 |
|
java.time.Period |
一段时间,基于日历单位,精确到天,例如:2年,3天,5个月 |
|
java.time.ZoneId/ZoneOffset |
时区 |
1.JDK8时间API:
基本都是不可变类
1.时间表示
Date类:
记录该对象表示的时刻的UTC时间到Epoch的毫秒数
不受时区影响,无论在哪个时区,同一时刻的UTC时间是相同的,保存的毫秒数也相同
关于时区问题
1.同一个Date对象在不同时区格式化输出的时间字符串不同,但是表示的是同一个时刻
public static void main(String[] args) throws ParseException { String dataStr = "2023-11-17 11:26:18"; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 同一个Date对象,表示北京时间2023-11-17 11:26:18这个时刻 Date date1 = dateFormat.parse(dataStr); // 东八区这个时刻的时间 System.out.println(date1+"-->"+date1.getTime()); // Fri Nov 17 11:26:18 CST 2023-->1700191578000 // 西八区这个时刻的时间 TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); System.out.println(date1+"-->"+date1.getTime()); // Thu Nov 16 19:26:18 PST 2023-->1700191578000 }
2.同一个时间字符串在在不同的时区表示不同时刻,解析出的Date对象不同,表示的时间不同
public static void main(String[] args) throws ParseException { String dataStr = "2023-11-17 11:26:18"; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 东八区的2023-11-17 11:26:18 Date date1 = dateFormat.parse(dataStr); System.out.println(date1+"-->"+date1.getTime()); // Fri Nov 17 11:26:18 CST 2023-->1700191578000 // 西八区的2023-11-17 11:26:18 dateFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); Date date2 = dateFormat.parse(dataStr); System.out.println(date2+"-->"+date2.getTime()); // Sat Nov 18 03:26:18 CST 2023-->1700249178000 }
Instant类:
一个long记录到epoch的秒数,一个int记录纳秒数
其他类是按不同单位存储时间,如LocalDate类中是year,month,day三个字段
2.时间操作
jdk8提供的时间类都有比较完善的时间操作的方法,大概是这几种,不同的类有针对不同单位的一些扩展,以LocalDateTime为例:
说明 |
举例 |
举例 |
---|---|---|
静态工厂方法,构建对象 |
LocalDateTime.now() LocalDateTime.of() LocalDateTime.ofxxx() |
Instant now=Instant.now(); LocalDateTime datetime = LocalDateTime.now(); LocalDateTime datetime1 = LocalDateTime.of(2023, 10, 21, 11, 6); LocalDateTime datetime2 = LocalDateTime.ofInstant(now, ZoneId.of("CTT")); LocalDateTime datetime3 = LocalDateTime.ofEpochSecond(now.getEpochSecond(),now.getNano(), zoneOffset); |
时间加减操作 支持不同单位 |
localDateTime.plus() localDateTime.plusSecond() localDateTime.plusxxx() |
LocalDateTime datetime7 = datetime.plusSeconds(3);
LocalDateTime datetime8 = datetime.plus(1000, ChronoUnit.MINUTES);
|
获取该时间的某个单位上的值 年份,月份,年的第几天,周几等 |
localDateTime.getDayOfWeek() localDateTime.getDayOfxxx() localDateTime.getMonth() localDateTime.getxxx() |
DayOfWeek dayOfWeek = datetime.getDayOfWeek(); int dayOfMonth = datetime.getDayOfMonth(); int dayOfYear = datetime.getDayOfYear(); Month month = datetime.getMonth(); int monthValue = datetime.getMonthValue(); int year = datetime.getYear(); |
修改 支持不同单位级别上的修改
|
localDateTime.with() localDateTime.withNano() localDateTime.withxxx() |
datetime.with(ChronoField.SECOND_OF_DAY,1000); LocalDateTime datetime4 = datetime.withNano(100); LocalDateTime datetime5 = datetime.withYear(1990); LocalDateTime datetime6 = datetime.withDayOfYear(99); |
计算到另一个时间的按照某单位的差值 |
localDateTime.util(Temporal endExclusive, TemporalUnit unit) |
|
格式化和解析 |
localDateTime.format() LocalDateTime.parse() |
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatted = datetime.format(dateTimeFormatter); LocalDateTime parsed = LocalDateTime.parse("2019-01-07 23:49:08"); |
Calendar类:
说明 |
方法 |
示例 |
---|---|---|
实例化,取当前时间 |
Calendar.getInstance() |
|
赋值 |
calendar.set(int field,int value) calendar.setTime(Date date) calendar.setTimeZone(TimeZone value) |
|
获取某个单位上的值 还提供了一些获取某些特殊值的能力,如某单位的最大最小值,某单位的String值等 |
calendar.get(int field) calendar.getxxx() |
int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); System.out.println(year + "年" + month + "月" + day + "日" + hour + "时" + minute + "分" + second + "秒"); // 2023年11月23日14时25分20秒 int maxDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); System.out.println(maxDayOfMonth);// 30 |
加减操作 add方法会在高位进位 |
calendar.add(int field,int amount) |
calendar.add(Calendar.MONTH,3); |
3.时间格式化
SimpleDateFormat
线程不安全
字符串解析过于宽容,容易出错
// 1.预定义的 DateFormat dateTimeInstance = SimpleDateFormat.getDateTimeInstance(); System.out.println(dateTimeInstance.format(new Date()));// 2023-11-22 15:02:00 // 2.自定义格式的 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(dateFormat.format(new Date()));// 2023-11-22 15:02:00 Date parsed = dateFormat.parse("2023-11-22 15:06:01", new ParsePosition(0));
DateTimeFormatter
线程安全
提供了一些预定义的Formtter
// 1.根据格式解析 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 2.DateTimeFormatterBuilder来构造 DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR) .appendLiteral("/") .appendValue(ChronoField.MONTH_OF_YEAR) .appendLiteral("/") .appendValue(ChronoField.DAY_OF_MONTH) .appendLiteral(" ") .appendValue(ChronoField.HOUR_OF_DAY) .appendLiteral(":") .appendValue(ChronoField.MINUTE_OF_HOUR) .appendLiteral(":") .appendValue(ChronoField.SECOND_OF_MINUTE) .appendLiteral(".") .appendValue(ChronoField.MILLI_OF_SECOND) .toFormatter(); // 3.用预定义的格式 DateTimeFormatter isoLocalDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;// '2011-12-03T10:15:30' // 4.用本地化的一些风格 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); System.out.println(dateTimeFormatter.format(LocalDateTime.now()));// 2023年11月22日 星期三 TemporalAccessor parse = dateTimeFormatter.parse("2023年11月22日 星期三"); LocalDate ldt = LocalDate.from(parse); System.out.println(ldt);// 2023-11-22
4.时间段
Period
通过年月日来对一段时间建模
Duration
通过秒和纳秒来对一段时间建模
5.时间单位
TemporaUnit
A unit of date-time, such as Days or Hours.
TemporaFeild
A field of date-time, such as month-of-year or hour-of-minute.
两者都提供了枚举实现
6.时区
ZoneId
一个表示时区的ID
ZoneOffset
表示时区和标准时间的差值