1. LocalDate vs LocalTime
LocalDate | LocalDateTime | |
---|---|---|
当前时间 | now() | now() |
自定义时间 | of() | of() |
修改时间 | with[Day Month Year]() | with[Nano Second Minute Hour]() |
获取时间属性 | get[Day Month Year]() | get[Nano Second Minute Hour]() |
转换时间 | toEpochDay() / toEpochSecond() | to[EpochSecond Nano Second]OfDay() |
数学运算 | [plus minus][Days Weeks Months Years]() | [plus minus][Nano Second Minute Hour]() |
时间比较 | isBefore() / isAfter() | isBefore() / isAfter() |
差值计算 | until() | until() |
闰年判断 | isLeapYear() | - |
LocalDateTime 这是对两者的一个参数整合,方法形式上大同小异
public class MyTimeTest {
@Test
public void test01(){
LocalDate now = LocalDate.now();
LocalDate date = LocalDate.of(2021, 10, 21);
System.out.println(date.toEpochDay());
LocalDate date2 = LocalDate.of(2021, Month.DECEMBER, 21);
LocalDate localDate1 = now.withMonth(12);
now.plusWeeks(1);
now.minusDays(1);
System.out.println(now.getDayOfMonth());
System.out.println(now.getDayOfWeek());
System.out.println(now.getDayOfYear());
System.out.println(now.getMonth());
System.out.println(now.getMonthValue());
System.out.println(now.getYear());
System.out.println(now.isBefore(LocalDate.now()));
Period period = now.until(LocalDate.now());
System.out.println(now.isLeapYear());
LocalTime localTime = LocalTime.now();
LocalTime time = LocalTime.of(1,1,1);
LocalTime time1 = LocalTime.of(1,1);
LocalTime localTime1 = time.withHour(12);
time.plusNanos(1);
time.minusSeconds(1);
System.out.println(time.getNano());
System.out.println(time.getSecond());
System.out.println(time.getMinute());
System.out.println(time.getHour());
System.out.println(time.toSecondOfDay());
System.out.println(time.toNanoOfDay());
System.out.println(time.isBefore(LocalTime.now()));
}
}
2. Duration vs Period
Duration 描述时间上LocalTime的差距;Period 描述时间上LocalDate的差距
Duration | Period | |
---|---|---|
获取两个时间之间的差距 | between() | between() |
创建时间 | of[Nanos Mills Seconds Minutes Days Hours]() | of[Days Weeks Months Years]() |
修改时间 | with[Seconds Nanos] | with[Days Months Years]() |
转换时间 | to[Nanos Millis Minutes Hours Days]() | toTotalMonths() |
get[Nacos Seconds]() | get[Days Months Years]() | |
获得对应部分数值 | to[Nanos Mills Seconds Minutes Days Hours]Part() | |
数学运算 | [plus minus][Nanos Mills Seconds Minutes Days Hours]() | [plus minus][Days Months Years]() |
乘法 | multipliedBy() | multipliedBy() |
除法 | dividedBy() | dividedBy() |
变为无效时间 | negated() | negated() |
是否是0 | isZero() | isZero() |
时间是否有效 | isNegative() | isNegative() |
public class MyTimeTest {
@Test
public void test02(){
// Duration
Duration duration = Duration.between(Instant.now(), Instant.now());
duration.withSeconds(1);
System.out.println(duration.plusSeconds(10));
System.out.println(duration.minusHours(1));
System.out.println(duration.multipliedBy(2));
System.out.println(duration.dividedBy(3));
System.out.println(duration.negated());
System.out.println(duration.isZero());
System.out.println(duration.isNegative());
// Period
Period of = Period.of(1, 1, 1);
System.out.println(of.getDays());
System.out.println(of.getMonths());
System.out.println(of.getYears());
of.plusDays(1);
of.minusMonths(2);
}
}
3. Instant
本质上等价于传统时间API中的
Date
属性,内部保存了从1970年1月1日 00:00:00以来的秒和纳秒。
方法 | |
---|---|
当前时间 | now() |
从秒中创建时间 | ofEpochSecond() |
数学运算 | [plus minus][Seconds Nanos Millis]() |
时间转换 | toEpochMilli() |
获取时间参数 | getNanos() getEpochSecond() |
时间大小判断 | isBefore() | isAfter() |
public class MyTimeTest {
@Test
public void test03(){
Instant instant = Instant.now();
Instant instant1 = Instant.ofEpochSecond(1000);
instant.plus(Duration.ofSeconds(10));
instant.plus(10, ChronoUnit.SECONDS);
instant.plusSeconds(10);
instant.plusNanos(10);
instant.minus(Duration.ofSeconds(10));
instant.minus(10, ChronoUnit.SECONDS);
instant.minusSeconds(10);
System.out.println(instant.toEpochMilli());
System.out.println(instant.getEpochSecond());
System.out.println(instant.getNano());
System.out.println(instant.isBefore(Instant.now()));
}
}
4. 时区设置
时区时间 ZonedDateTime 方法大体上和DateTime相同,LocalDate、LocalTime、LocalDateTime是不带时区的,带时区的日期时间类分为:ZonedDate、ZonedTime、ZonedDateTime。其中每个时区都对应着 ID,ID的格式为 “区域/城市” 。例如 :Asia/Shanghai 等。
ZoneId:该类中包含了所有的时区信息。
相关方法类似于LocalDateTime中的相关方法。
ZonedDateTime | 方法 |
---|---|
获取偏移 | getOffset() |
类型转换 | toLocalDate() |
toLocalTime() | |
toLocalDateTime() | |
toInstant() |
ZoneId | 方法 |
---|---|
获取实例 | of(“America/Vancouver”) |
获得有效的时区参数 | getAvailableZoneIds() |
public class MyTimeTest {
@Test
public void test06(){
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/Vancouver"));
ZonedDateTime now1 = ZonedDateTime.now(ZoneId.of("America/Vancouver"));
ZoneOffset offset = now.getOffset();
LocalDate localDate = now.toLocalDate();
LocalTime localTime = now.toLocalTime();
LocalDateTime localDateTime = now.toLocalDateTime();
Instant instant = now.toInstant();
ZoneId.getAvailableZoneIds().forEach(System.out::println);
}
}
5. 时间调整器
使用TemporalAdjusters实现工具类完成调整
可以使用TemporalAdjusters.ofDateAdjuster 实现自定义工具类的创建
public class MyTimeTest {
@Test
public void test04(){
LocalDate localDate = LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth());
LocalDate localDate1 = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
// 自定义TemporalAdjusters
TemporalAdjuster adjuster = TemporalAdjusters.ofDateAdjuster(w -> {
LocalDate result = w;
do {
result = result.plusDays(1);
} while (result.getDayOfWeek().getValue() >= 6);
return result;
});
localDate.with(adjuster);
// 另外一种表示形式
TemporalAdjuster adjuster2 = w -> {
LocalDate result = (LocalDate) w;
do {
result = result.plusDays(1);
} while (result.getDayOfWeek().getValue() >= 6);
return result;
};
localDate.with(adjuster);
}
}
6. 时间格式化
预定义的格式化器
这种形式的格式化器主要是为了机器可读而设计的,如果是前端可视化更推荐使用Locale的表示形式
格式器 | 描述 | 示例 |
---|---|---|
BASIC_ISO_DATE | 年、月、日、时区偏移量,中间没有分隔符 | 19690716-0500 |
ISO_LOCAL_DATE,ISO_L0CAL_TIME,ISO_LOCAL DATE TINE | 分隔符为·、:、T | 1969-07-16, 09:32:00, 1969-07-16T09:32:00 |
ISO_OFFSET_DATE, ISO OFFSETTIME, ISO_OFFSET_DATETIME | 类似ISO_L0CAL_XXX, 但是有时区偏移量 | 1969-07-16-05:00, 09:32:00-05:00, 1969-07-16T09:32:00-05:00 |
ISO_ZONED_DATETIME | 有时区偏移量和时区ID | 1969-07-16T 09:32:00-05:00 [America/NewYork] |
ISO_INSTANT | 在UTC中, 用Z时区ID来表示 | 1969-07-16T14:32:00Z |
ISO_DATE, ISO_TIME, ISODATETIME | 类似ISO_OFFSET_DATE、ISO_OFFSET_TIME和ISO ZONEDDATE_TIME, 但是时区信息是可选的 | 1969-07-16-05:00,09:32:00-05:00,1969-07-16T 09:32:00-05:00[America/NewYork] |
ISO_ORDINAL DATE | Local Date的年和年日期 | 1969-197 |
ISO_WEEK DATE | Local Date的年、星期和星期日期 | 1969-W29-3 |
RFC1123DATETINE | 用于邮件时间戳的标准, 编纂于RFC 822,并在RFC 1123中将年份更新到4位 | Wed,16Jul 1969 09:32:00-0500 |
locale相关的格式化风格
风格 | 日期 | 时间 |
---|---|---|
SHORT | 7/16/69 | 9:32 AM |
MEDIUM | Jul 16,1969 | 9:32:00 AM |
LONG | July 16,1969 | 9:32 AM EDT |
FULL | Wednesday,July 16,1969 | 9:32 AM EDT |
常用日期格式化符号
时间域或目的 | 示例 |
---|---|
ERA | G:AD, GGGG:An no Domini, G GGGG:A |
YEAR_OF_ERA | yy:69,yyyy:1969 |
MONTH OF YEAR | M:7, MM:07, MMM:Jul, MMMM:JuLy, M MMMM:J |
DAY_OF MONTH | d:6,dd:06 |
DAYOFWEEK | e:3, E:Wed, EEEE:Wednesday, E EEEE:W |
HOUR OF DAY | H:9,HH:09 |
CLOCK HOUR_OF_AM PM | K:9,KK:09 |
AM PM OF DAY | a:AM |
MINUTE_OF HOUR | mm:02 |
SECOND OF MINUTE | ss:00 |
NANO OF SECOND | nnnnnn:000000 |
时区ID | W:America/New_York |
时区名 | Z:EDI, zzzz:Eastern DayLight Time V:ET, WV V:Eastern time |
时区偏移量 | x:-04,xx:-0400,X:-0400,xxx:-04:00,XXX:与xxx相同,但是Z表示0 |
本地化的时区偏移量 | 0:GMT-4, 0000:GMT-04: 00 |
修改后的儒略日 | g:58243 |
DateTimeFormatter | 方法 |
---|---|
格式化方法 | format() |
格式化风格 | ofLocalizedDateTime() |
切换Locale | withLocale() |
自定义格式化器 | ofPattern() |
LocalDate解析 | parse() |
LocalDate格式化 | format() |
ZonedDateTime解析 | parse() |
注意:withLocale():修改格式化解析形式,例如星期格式化中,
Locale.English
vsLocale.China
对应就是Tue
和星期二
public class MyTimeTest {
@Test
public void test05(){
// 使用标准格式化器
String format = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now());
String format1 = LocalTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);
// 使用Locale的格式化风格
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
DateTimeFormatter locale = formatter.withLocale(Locale.CANADA);// 切换不同时区的格式化器
System.out.println(locale.format(ZonedDateTime.now()));
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime.parse("星期二 2021-12-21 11:11:11", pattern);
LocalDateTime.parse("Tue 2021-12-21 11:11:11", pattern.withLocale(Locale.ENGLISH));
}
}
7. 遗留类的转换
Instant
类似于Date
,ZonedDateTime
类似于GregorianCalendar
时间类转换关系
类 | 转换到遗留类 | 转换自遗留类 |
---|---|---|
Instant ◇java.util.Date | Date.from(instant) | date.toInstant() |
ZonedDateTime ◇java.util.GregorianCalendar | GregorianCalendar.from(zoned DateTime) | cal.toZonedDateTime() |
Instant ◇java.sql.Timestamp | TimeStamp.from(instant) | timestamp.toInstant() |
LocalDateTime ◇java.sqL.Timestamp | Timestamp.valueOf(Local DateTime) | timeStamp.toLocal DateTime() |
LocalDate ◇java.sql.Date | Date. valueOf(local Date) | date.toLocalDate() |
LocalTime ◇java.sql.Time | Time.valueOf(Local T me) | time.toLocalTime() |
DateTime Formatter ◇java.text.DateFormat | formatter.toFormat() | 无 |
java.util.TimeZone ◇ZoneId | Timezone.getTimeZone(id) | timeZone.toZoneId() |
java.nio.file.attribute.FileTime ◇Instant | FileTime.from(instant) | fileTime.toInstant() |
public class MyTimeTest {
@Test
public void test07(){
// Instant <-> Date
Date.from(Instant.now());
new Date().toInstant();
// ZonedDateTime <-> GregorianCalendar
GregorianCalendar.from(ZonedDateTime.now());
(new GregorianCalendar()).toZonedDateTime();
// Instant <-> TimeStamp
Timestamp.from(Instant.now());
(new Timestamp()).toInstant();
// LocalDateTime <-> TimeStamp
Timestamp.valueOf(LocalDateTime.now());
(new Timestamp()).toLocalDateTime();
// LocalDate <-> Date
java.sql.Date.valueOf(LocalDate.now());
(new java.sql.Date()).toLocalDate();
// LocalTime <-> Time
Time.valueOf(LocalTime.now());
(new Time()).toLocalTime();
// TimeZone <-> ZoneId
TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"));
(new TimeZone()).toZoneId();
}
}