关于java:JDK18新增日期时间类型

39次阅读

共计 8784 个字符,预计需要花费 22 分钟才能阅读完成。

如果咱们能够跟他人说:“咱们在下午见面,别晚了!”那么就再简略不过了。然而咱们心愿工夫与昼夜和四季无关,于是事件就变简单了。Java1.0 中蕴含了一个 Date 类,然而它的大多数办法曾经在 Java 1.1 引入 Calendar 类之后被弃用了。而 Calendar 并不比 Date 好多少。它们面临的问题是:

可变性:象日期和工夫这样的类应该是不可变的。Calendar 类中能够应用三种办法更改日历字段:set()、add() 和 roll()。
偏移性:Date 中的年份是从 1900 开始的,而月份都是从 0 开始的。
格式化:格式化只对 Date 有用,Calendar 则不行。
此外,它们也不是线程平安的,不能解决闰秒等。
Date 的 API:

只管 Date 类打算反映协调世界时 (UTC),但无奈做到如此精确,这取决于 Java 虚拟机的主机环境。以后简直所有操作系统都假设 1 天 = 24 × 60 × 60 = 86400 秒。但对于 UTC,大概每一两年呈现一次额定的一秒,称为“闰秒”。闰秒始终作为当天的最初一秒减少,并且始终在 12 月 31 日或 6 月 30 日减少。例如,1995 年的最初一分钟是 61 秒,因为减少了闰秒。大多数计算机时钟不是特地的精确,因而不能反映闰秒的差异。

在类 Date 所有能够承受或返回年、月、日期、小时、分钟和秒值的办法中,将应用上面的示意模式:

l 年份 y 由整数 y – 1900 示意。

l 月份由从 0 至 11 的整数示意;0 是一月、1 是二月等等;因而 11 是十二月。

l 日期(一月中的某天)按通常形式由整数 1 至 31 示意。

l 小时由从 0 至 23 的整数示意。因而,从午夜到 1 a.m. 的工夫是 0 点,从中午到 1 p.m. 的工夫是 12 点。

l 分钟按通常形式由 0 至 59 的整数示意。

l 秒由 0 至 61 的整数示意;值 60 和 61 只对闰秒产生,只管那样,也只用在理论正确跟踪闰秒的 Java 实现中。于按以后引入闰秒的形式,两个闰秒在同一分钟内产生是极不可能的,但此标准遵循 ISO C 的日期和工夫约定。

在所有情景中,针对这些目标赋予办法的参数不须要在指定的范畴内;例如,能够把日期指定为 1 月 32 日,并把它解释为 2 月 1 日的雷同含意。

Date date = new Date(2017-1900,8-1,28);

System.out.println(date);//Mon Aug 28 00:00:00 CST 2017

能够说,对日期和工夫的操作始终是 Java 程序员最苦楚的中央之一。第三次引入的 API 是胜利的,并且 java 8 中引入的 java.time API 曾经纠正了过来的缺点,未来很长一段时间内它都会为咱们服务。

Java 8 排汇了 Joda-Time 的精髓,以一个新的开始为 Java 创立优良的 API。

time – 蕴含值对象的根底包
time.chrono – 提供对不同的日历零碎的拜访。
time.format – 格式化和解析工夫和日期
time.temporal – 包含底层框架和扩大个性
time.zone – 蕴含时区反对的类
Java 8 排汇了 Joda-Time 的精髓,以一个新的开始为 Java 创立优良的 API。新的 java.time 中蕴含了所有对于时钟(Clock),本地日期(LocalDate)、本地工夫(LocalTime)、本地日期工夫(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 办法,用于把 Date 转换成新的示意模式。这些新增的本地化工夫日期 API 大大简化了了日期工夫和本地化的治理。

阐明:大多数开发者只会用到根底包和 format 包,也可能会用到 temporal 包。因而,只管有 68 个新的公开类型,大多数开发者,大略将只会用到其中的三分之一。

java.time

注:ISO-8601 日历零碎是国际标准化组织制订的古代公民的日期和工夫的表示法,也就是公历。

java.time.chrono

java.time
1、本地日期(LocalDate)、本地工夫(LocalTime)、本地日期工夫(LocalDateTime)
LocalDate 代表 IOS 格局(yyyy-MM-dd)的日期, 能够存储 生日、纪念日等日期。

LocalTime 示意一个工夫,而不是日期

LocalDateTime 是用来示意日期和工夫的,这是一个最罕用的类之一。

形容

now() / now(ZoneId zone)

静态方法,依据以后工夫创建对象 / 指定时区的对象

of()

静态方法,依据指定日期 / 工夫创建对象

getDayOfMonth()/getDayOfYear()

取得月份天数(1-31) / 取得年份天数(1-366)

getDayOfWeek()

取得星期几(返回一个 DayOfWeek 枚举值)

getMonth()

取得月份, 返回一个 Month 枚举值

getMonthValue() / getYear()

取得月份(1-12) / 取得年份

getHours()/getMinute()/getSecond()

取得以后对象对应的小时、分钟、秒

withDayOfMonth()/withDayOfYear()/withMonth()/withYear()

将月份天数、年份天数、月份、年份批改为指定的值并返回新的对象

with(TemporalAdjuster t)

将以后日期工夫设置为校对器指定的日期工夫

plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()

向以后对象增加几天、几周、几个月、几年、几小时

minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()

从以后对象减去几月、几周、几天、几年、几小时

plus(TemporalAmount t)/minus(TemporalAmount t)

增加或缩小一个 Duration 或 Period

isBefore()/isAfter()

比拟两个 LocalDate

isLeapYear()

判断是否是平年(在 LocalDate 类中申明)

format(DateTimeFormatter t)

格式化本地日期、工夫,返回一个字符串

parse(Charsequence text)

将指定格局的字符串解析为日期、工夫

//now()
@Test
public void testLocalDateTime(){
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime datetime = LocalDateTime.now();
}
//of()或 parse
@Test
public void testLocalDate() {
// LocalDate date = LocalDate.now();
// LocalDate date = LocalDate.of(2017, 3, 20);
LocalDate date = LocalDate.parse(“2017-03-12”);
}
public static void main(String[] args) {
LocalDateTime t = LocalDateTime.now();
System.out.println(“这一天是这一年的第几天:”+t.getDayOfYear());
System.out.println(“年:”+t.getYear());
System.out.println(“月:”+t.getMonth());
System.out.println(“月份值:”+t.getMonthValue());
System.out.println(“日:”+t.getDayOfMonth());
System.out.println(“星期:”+t.getDayOfWeek());
System.out.println(“时:”+t.getHour());
System.out.println(“分:”+t.getMinute());
System.out.println(“秒:”+t.getSecond());
System.out.println(t.getMonthValue());
}
@Test
public void testLocalDate2() {
LocalDate date = LocalDate.now();

//withXxx()办法,不扭转原来的 date 对象,返回一个新的对象,不可变性
// LocalDate date2 = date.withDayOfMonth(1);// 获取这个月的第一天
LocalDate date2 = date.with(TemporalAdjusters.firstDayOfMonth());// 获取这个月的第一天
System.out.println(date2);

// 获取这个月的最初一天
LocalDate date3 = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(date3);

//45 天后的日期
LocalDate date4 = date.plusDays(45);
System.out.println(date4);

//20 天前的日期
LocalDate date5 = date.minusDays(20);
System.out.println(date5);

boolean before = date.isBefore(date5);
System.out.println(date+”是否比”+date5+”早”+ before);

System.out.println(date+”是否是平年:”+date.isLeapYear());

}
MonthDay month = MonthDay.of(8, 14);
MonthDay today = MonthDay.from(date);
System.out.println(“明天是否是生日:”+ month.equals(today));
2、刹时:Instant
Instant:工夫线上的一个刹时点。这可能被用来记录应用程序中的事件工夫戳。

在解决工夫和日期的时候,咱们通常会想到年, 月, 日, 时, 分, 秒。然而,这只是工夫的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是间断的。在此模型中,工夫线中的一个点示意为一个很大的数,这有利于计算机解决。在 UNIX 中,这个数从 1970 年开始,以秒为的单位;同样的,在 Java 中,也是从 1970 年开始,但以毫秒为单位。

java.time 包通过值类型 Instant 提供机器视图。Instant 示意工夫线上的一点,而不须要任何上下文信息,例如,时区。概念上讲,它只是简略的示意自 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC)开始的秒数。因为 java.time 包是基于纳秒计算的,所以 Instant 的精度能够达到纳秒级。

工夫戳:指格林威治工夫 1970 年 01 月 01 日 00 时 00 分 00 秒(北京工夫 1970 年 01 月 01 日 08 时 00 分 00 秒)起至当初的总秒数。

public static void main(String[] args) {
Instant t = Instant.now();
System.out.println(t);

// 偏移 8 个小时
OffsetDateTime atOffset = t.atOffset(ZoneOffset.ofHours(8));
System.out.println(atOffset);

long milli = t.toEpochMilli();
System.out.println(milli);

Instant in2 = Instant.ofEpochSecond(10000000);
System.out.println(in2);
}
3、带时区的日期、工夫的解决
作为一个开发者,如果不必去解决时区和它带来的复杂性,那是侥幸的。java.time 包下的 LocalDate、LocalTime、LocalDateTime 和 Instant 根本能满足需要。当你不可避免时区时,ZonedDateTime 等类能够满足咱们的需要。

ZonedDateTime:一个在 ISO-8601 日历零碎时区的日期工夫,如 2007-12-03T10:15:30+01:00 Europe/Paris。

其中每个时区都对应着 ID,地区 ID 都为“{区域}/{城市}”的格局,例如:Asia/Shanghai 等
now():应用零碎工夫获取以后的 ZonedDateTime
now(ZoneId):返回指定时区的 ZonedDateTime
ZoneId:该类中蕴含了所有的时区信息,一个时区的 ID,如 Europe/Paris

getAvailableZoneIds():静态方法,能够获取所有时区信息
of(String id):静态方法,用指定的时区信息获取 ZoneId 对象
Clock:应用时区提供对以后即时、日期和工夫的拜访的时钟。

public static void main(String[] args) {
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for (String string : availableZoneIds) {
System.out.println(string);
}

ZonedDateTime t = ZonedDateTime.now();
System.out.println(t);

ZonedDateTime t1 = ZonedDateTime.now(ZoneId.of(“America/New_York”));
System.out.println(t1);

// Clock clock = Clock.systemDefaultZone();
Clock c = Clock.system(ZoneId.of(“America/New_York”));
System.out.println(c.getZone());
System.out.println(c.instant());
}
4、持续时间:Duration
Duration: 用于计算两个“工夫”距离

public static void main(String[] args) {
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());
}
5、日期距离:Period
Period: 用于计算两个“日期”距离

public static void main(String[] args) {
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());// 1 年
System.out.println(“相差的月数:”+between.getMonths());// 又 7 个月
System.out.println(“相差的天数:”+between.getDays());// 零 25 天
System.out.println(“相差的总数:”+between.toTotalMonths());// 总共 19 个月
}
10.8.2 java.time.temporal .TemporalAdjuster : 工夫校正器
TemporalAdjuster : 工夫校正器。有时咱们可能须要获取例如:将日期调整到“下一个工作日”等操作。

TemporalAdjusters : 该类通过静态方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx()) 提供了大量的罕用 TemporalAdjuster 的实现。

public static void main(String[] args) {
LocalDate now = LocalDate.now();
System.out.println(“下一个周日:”+now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)));
System.out.println(“下周五”+ now.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)));
System.out.println(“本月最初一天:”+now.with(TemporalAdjusters.lastDayOfMonth()));//2017-08-31
LocalDate week = LocalDate.now().with(new TemporalAdjuster(){
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = (LocalDate) temporal;
if(date.getDayOfWeek().equals(DayOfWeek.MONDAY)){
return date.plusDays(7);
}else if(date.getDayOfWeek().equals(DayOfWeek.TUESDAY)){
return date.plusDays(6);
}else if(date.getDayOfWeek().equals(DayOfWeek.WEDNESDAY)){
return date.plusDays(5);
}else if(date.getDayOfWeek().equals(DayOfWeek.THURSDAY)){
return date.plusDays(4);
}else 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(“下一个工作日:”+ week);
}
10.8.3 java.time.format.DateTimeFormatter 类
该类提供了三种格式化办法:

预约义的规范格局。如:ISO_DATE_TIME;ISO_DATE

本地化相干的格局。如:ofLocalizedDate(FormatStyle.MEDIUM)

自定义的格局。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

public static void main(String[] args) {
System.out.println(DateTimeFormatter.ISO_DATE.format(LocalDate.now()));
System.out.println(DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now()));

//FULL 和 SHORT 实用于 LocalDate 和 LocalTime
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(LocalDate.now()));
System.out.println(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(LocalTime.now()));

//LONG 和 MEDIUM 实用于 LocalDateTime
System.out.println(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(LocalDateTime.now()));

DateTimeFormatter op = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”);
System.out.println(op.format(LocalDateTime.now()));
}
10.8.4 与传统日期解决的转换类

理解更多 java 培训相干技术内容欢送关注小编!

正文完
 0