Instant 时间戳
用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算 。
// 2023-07-04T09:02:39.456Z
Instant instant1 = Instant.now(); // 默认获取UTC时区
// 2023-07-04T17:02:39.456+08:00
OffsetDateTime offsetDateTime = instant1.atOffset(ZoneOffset.ofHours(8));
// 获取时间戳 1688461359456
System.out.println(instant1.toEpochMilli());
// 以Unix元年为起点,进行偏移量运算
// 1970-01-01T00:01:00Z
Instant instant2 = Instant.ofEpochSecond(60);
Period 日期之间的差
两个类表示时间量或两个日期之间的差,两者之间的差异为:Period基于日期值,而Duration基于时间值。
LocalDate startDate = LocalDate.of(2015, 2, 20);
LocalDate endDate = LocalDate.of(2017, 1, 15);
// Period 类表示一段时间的年、月、日,使用between()方法获取两个日期之间的差作为Period 对象返回
Period period = Period.between(startDate, endDate);
// Years:1 months:10 days:26
System.out.println("Years:" + period.getYears() +
" months:" + period.getMonths() +
" days:"+period.getDays());
// 另一个创建Period类型对象是基于年、月、日和周
// 3 10 10
Period fromUnits = Period.of(3, 10, 10);
// 0 0 50
Period fromDays = Period.ofDays(50);
// 0 5 0
Period fromMonths = Period.ofMonths(5);
// 10 0 0
Period fromYears = Period.ofYears(10);
// 0 0 280
Period fromWeeks = Period.ofWeeks(40);
// period的值可以通过plusX()、minusX()方法进行增加或减少,其中X表示日期单元
// 330
int days = fromWeeks.plusDays(50).getDays();
// -2
int days2 = fromWeeks.minusMonths(2).getMonths();
Duration 时间之间的差
Duration类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性。我们能使用between()方法比较两个瞬间的差。
Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
Instant end = Instant.parse("2017-10-03T10:14:30.00Z");
Duration duration = Duration.between(start, end);
// 60
System.out.println(duration.getSeconds());
// 判断前面时间是否晚于后面时间 true
boolean negative = duration.isNegative();
// 我们能基于下面的方法获得Duration对象,ofDays(), ofHours(), ofMillis(), ofMinutes(), ofNanos(), ofSeconds():
Duration fromDays = Duration.ofDays(1);
Duration fromMinutes = Duration.ofMinutes(60);
// 可以使用toDays(), toHours(), toMillis(), toMinutes()方法把Duration对象可以转成其他时间单元
duration.toDays();
// 也可以通过 plusX()、minusX()方法增加或减少Duration对象,其中X表示days, hours, millis, minutes, nanos 或 seconds
// 也可以使用plus()和minus()方法带TemporalUnit 类型参数进行加减
duration.plus(60, ChronoUnit.SECONDS).getSeconds();
duration.minus(30, ChronoUnit.SECONDS).getSeconds();
Clock 时钟
Clock类提供了访问当前日期和时间的方法,Clock 是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用 Instant 类来表示,Instant 类也可以用来创建老的 java.util.Date 对象。
Clock clock = Clock.systemDefaultZone();
// 1688376161352
long millis = clock.millis();
Instant instant = clock.instant();
// Mon Jul 03 17:22:41 CST 2023
Date legacyDate = Date.from(instant); // legacy java.util.Date
Timezones时区
在新 AP I中时区使用 ZoneId 来表示。时区可以很方便的使用静态方法 of 来获取到。时区定义了到 UTS 时间的时间差,在 Instant 时间点对象到本地日期对象之间转换的时候是极其重要的。
// [Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, America/Marigot,
// Asia/Aqtau, Pacific/Kwajalein, America/El_Salvador, Asia/Pontianak, Africa/Cairo,
// 还有好多,应该是打印所有的时区
System.out.println(ZoneId.getAvailableZoneIds());
// prints all available timezone ids
// 德国柏林
ZoneId zone1 = ZoneId.of("Europe/Berlin");
// 可能是巴西时区
ZoneId zone2 = ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
// ZoneRules[currentStandardOffset=+01:00]
// ZoneRules[currentStandardOffset=-03:00]
LocalDate 本地日期
LocalDate 表示了一个确切的日期,比如 2014-03-11
。该对象值是不可变
的,用起来和 LocalTime 基本一致。下面的例子展示了如何给 Date 对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。
public class InterfaceDemo {
public static void main(String[] args) {
// 构造日期
// 2023-07-04
LocalDate today = LocalDate.now();
// 设置日期,返回2099-02-28
LocalDate now2 = LocalDate.of(2099, 2, 28);
// 2022-07-04
LocalDate independenceDay = LocalDate.of(2022, Month.JULY, 4);
// 字符串转日期
LocalDate endOfFeb = LocalDate.parse("2018-02-28");
// 严格按照yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式
// 获取当前日期的相关信息
// 今天是几号 25
int dayofMonth = today.getDayOfMonth();
// 今年是一年中的哪一天,176
int dayofYear = today.getDayOfYear();
// MONDAY
DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();
// 对当前日期进行操作
// 2023-07-05
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
// 2023-07-03
LocalDate yesterday = tomorrow.minusDays(2);
// 取本月第1天:2023-07-01
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2018-04-01
// 取本月第2天:2023-07-02
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2018-04-02
// 这些只是单纯的获取日期,可见其能够获取日期的种类多种多样,比原来的Date型好用太多,尤其是过去的Date型,月份计算居然是从0开始,不是一般的反人类了。
// LocalDate更加强大的地方还没展示
// 取本月最后一天,2023-07-31,再也不用计算是28,29,30还是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2018-04-30
// 取下一天:2023-08-01
LocalDate firstDayOfNextMonth = lastDayOfThisMonth.plusDays(1);
// 取2017年1月第一个周一:2017-01-02
LocalDate firstMondayOf2017 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
System.out.println("========================================================");
// 从字符串解析一个 LocalDate 类型和解析 LocalTime 一样简单。代码如下:
DateTimeFormatter germanFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.GERMAN);
// // 2014-12-24
LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter);
// 另外,LocalDate的格式化不要用SimpleDateFormat的方法。
LocalDate today2 = LocalDate.now();
DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
// 2023年07月04日
String text = today2.format(formatters);
}
}
LocalTime 本地时间
LocalTime定义了一个没有时区信息的时间,例如 晚上 10 点,或者 17:30:15。下面的例子使用前面代码创建的时区创建了两个本地时间。之后比较时间并以小时和分钟为单位计算两个时间的时间差。
// 获得当前时间
LocalTime now = LocalTime.now();
// 构造时间
LocalTime zero = LocalTime.of(0, 0, 0); // 00:00:00
// 字符串转时间
LocalTime mid = LocalTime.parse("12:00:00"); // 12:00:00
System.out.println(zero.isBefore(mid)); // true
long hoursBetween = ChronoUnit.HOURS.between(zero, mid);
long minutesBetween = ChronoUnit.MINUTES.between(zero, mid);
System.out.println(hoursBetween); // 间隔12小时
System.out.println(minutesBetween); // 间隔720分钟
// LocalTime提供了多种工厂方法来简化对象的创建,包括解析时间字符串。
DateTimeFormatter germanFormatter = DateTimeFormatter
// 本地化相关的格式
// FormatStyle是一个内置的枚举,提供了一些值FULL、LONG、MEDIUM和SHORT
// FormatStyle 描述 日期样式 时间样式 日期和时间样式
// FULL 高度详细 2020年8月13日星期四 上午12:43:00中欧夏令时 2020年8月13日星期四上午12:43:48中欧夏令时
// LONG 包含大部分细节 2020年8月13日 上午12:45:27中欧夏令时 2020年8月13日上午12:44:40中欧夏令时
// MEDIUM 包含一些细节 2020年8月13日 上午12:45:49 2020年8月13日,上午12:46:29
// SHORT 通常是数字和最短可能 20/8/13 上午12:47 20/8/13,上午12:47
.ofLocalizedTime(FormatStyle.SHORT)
// 德国,这个用English和Chinese都会报错
// 网上也找不到这个的具体用法
.withLocale(Locale.GERMAN);
LocalTime leetTime = LocalTime.parse("13:37", germanFormatter);
System.out.println(leetTime); // 13:37
LocalDateTime 本地日期时间
LocalDateTime同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。
Java的Date,Calendar
类型使用起来并不是很方便,而且Date类(据说)有着线程不安全等诸多弊端。同时若不进行封装,会在每次使用时特别麻烦。于是Java8推出了线程安全、简易、高可靠的时间包。并且数据库中也支持LocalDateTime类型,在数据存储时候使时间变得简单。
Java8这次新推出的包括三个相关的时间类型:
- LocalTime时分秒纳秒
- LocalDate年月日
- LocalDateTime年月日时分秒
LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
DayOfWeek dayOfWeek = sylvester.getDayOfWeek();
System.out.println(dayOfWeek); // WEDNESDAY
Month month = sylvester.getMonth();
System.out.println(month); // DECEMBER
long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay); // 1439
// 只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date。代码如下:
Instant instant = sylvester
.atZone(ZoneId.systemDefault())
.toInstant();
Date legacyDate = Date.from(instant);
System.out.println(legacyDate); // Wed Dec 31 23:59:59 CET 2014
// 格式化LocalDateTime和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义格式。代码如下:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd, yyyy - HH:mm");
LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter);
String string = formatter.format(parsed);
System.out.println(string); // Nov 03, 2014 - 07:13
// 和java.text.NumberFormat不一样的是新版的DateTimeFormatter是不可变的,所以它是线程安全的。
日期格式化
package com.example.javasestudy.localdatetime;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@SpringBootTest
public class TestLocalDateTime {
@Test
void contextLoads() {
// DateTimeFormatter 代替 Calendar的SimpleDateFormat,
LocalDateTime of = LocalDateTime.of(2024, 4, 1, 11, 40, 50);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String format = dateTimeFormatter.format(of);
DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
LocalDateTime parse = LocalDateTime.parse(format, dateTimeFormatter2);
// T的问题暂时没有好的解决办法,网上说可以使用配置类来解决,还没尝试过,可以的话这是最好的办法
// 或者在字段上加注解,或者使用字符串替换(这应该是最逼不得已的办法吧)
// 这个问题的原因是,LocalDateTime的重写toString的时候加上的
// return date.toString() + 'T' + time.toString();
// 2024-04-01T11:40:50
System.out.println(of);
// 2024年04月01日 11时40分50秒
System.out.println(format);
// 2024-04-01T11:40:50
System.out.println(parse);
}
}
JDBC映射
最新JDBC映射将把数据库的日期类型和Java 8的新类型关联起来:
SQL -> Java
--------------------------
date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime
部分内容转载自:
https://blog.csdn.net/u011055819/article/details/80070429
https://www.cnblogs.com/wmyskxz/p/13527583.html
https://blog.csdn.net/neweastsun/article/details/88770592
有的时候,人们把他们装出的那一面做的如此完美,随着时间的推移,他们似乎真的变成了他们所装扮的那个人了。
月亮与六便士
威廉·萨默赛特·毛姆