护肤品网站建设的意义,天河区进一步,网站建设合同违约条款,WORDPRESS论坛文章阅读统计插件一#xff1a;时间日期API的演进#xff0c;及存在的问题
JDK 1.0 时期#xff1a;
对于日期和时间的支持只能依赖于java.util.Date类。它的最小精度是毫秒起始年份为1900年#xff0c;起始月份为0。20180822表示为new Date (118,7,22)返回值使用JVM默认时区#xff1a;…一时间日期API的演进及存在的问题
JDK 1.0 时期
对于日期和时间的支持只能依赖于java.util.Date类。它的最小精度是毫秒起始年份为1900年起始月份为0。20180822表示为new Date (118,7,22)返回值使用JVM默认时区CST。但是并不支持时区
JDK 1.1 时期
废弃了java.util.Date的一些方法转而用java.util.Calendar替代Calendar的起始月份依旧是0格式化及解析时间使用DateFormat方法非线程安全Date、Calendar类都是可变的
JDK 1.8 时期 Java 8在java.time包中整合了很多Joda-Time的特性使得API更加好用。API主要包含类 LocalDate、LocalTime、Instant、Duration和Period
二新的日期时间API
LocalDate、LocalTime、Instant、Duration和Period
LocalDate日期 该类的实例是一个不可变对象它只提供简单的日期不包含当天的时间也不包含时区相关信息。可以使用静态工厂创建LocalDate实例。
LocalDate常见用法 LocalDate date LocalDate.of(2019, 4, 10);System.out.println(date.getYear());//2019System.out.println(date.getMonthValue());//4System.out.println(date.getDayOfYear());//100System.out.println(date.getDayOfMonth());//10System.out.println(date.getDayOfWeek());//WEDNESDAYSystem.out.println(date.isLeapYear());//falseSystem.out.println(date.lengthOfMonth());//30System.out.println(date.lengthOfYear());//365System.out.println(LocalDate.now().atStartOfDay());//2019-04-10T00:00LocalTime时间
与LocalDate类似LocalTime表示时间同样可以使用of方法创建LocalTime实例。 另外LocalDate、LocalTime都支持从字符串创建
//LocalDate、LocalTime都是final的
LocalDatelocalDate LocalDate.parse(2019-04-10);
LocalTime localTime LocalTime.parse(10:48:33);LocalTime localTime2 LocalTime.of(10, 48, 33);
System.out.println(localTime2.getHour());//10
System.out.println(localTime2.getMinute());//48
System.out.println(localTime2.getSecond());//33
System.out.println(localTime2.getNano());//当前LocalTime的秒的纳秒数0LocalDateTime日期和时间 System.out.println(LocalDateTime.now());//2019-04-10T11:00:05.627System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.now()));//2019-04-10T11:00:05.628System.out.println(LocalDateTime.parse(2019-04-10T10:58:01));//2019-04-10T10:58:01System.out.println(LocalDateTime.of(2019, 4, 10, 10, 58, 00, 19999));//2019-04-10T10:58:00.000019999//可以把LocalDateTime拆分为LocalDate和LocalTimeLocalDateTime l1 LocalDateTime.now();System.out.println(l1.toLocalDate());//2019-04-10System.out.println(l1.toLocalTime());//11:02:34.827Instant机器的日期和时间 Instant设计初衷是便于机器使用包含的是秒及纳秒所组成的数字。所以一般编程不会用到此API。 java.time.Instant类对时间的建模方式是以Unix元年时间UTC时区1970-01-01 00:0000开始进行计算
System.out.println(Instant.ofEpochMilli(763883333l));//1970-01-09T20:11:23.333Z//参数1秒参数2纳秒参数2对参数1进行调整System.out.println(Instant.ofEpochSecond(1, 8999999999999999999l));//2255-03-14T16:00:00.999999999ZDuration、Period时间段
由于LocalDateTime和Instant是为不同的目的而设计的一个是为了人阅读的一个是为了机器处理的所以不能将二者混用。此外由于Duration类主要用于以秒和纳秒衡量时间的长短所以不能向between方法传递LocalDate
Duration和Period类都提供了很多非常方便的工厂类直接创建对应的实例
//计算日期时间差使用这两个类
LocalDateTime l1 LocalDateTime.parse(2019-04-01T15:10:10);
LocalDateTime l2 LocalDateTime.now();//2019-04-10T11:40:10
System.out.println(Duration.between(l1, l2).toDays());//8
System.out.println(Period.between(l1.toLocalDate(), l2.toLocalDate()).getDays());//9Duration threeMinutes Duration.ofMinutes(3);
Duration threeMinutes Duration.of(3, ChronoUnit.MINUTES);Period tenDays Period.ofDays(10);
Period threeWeeks Period.ofWeeks(3);
Period twoYearsSixMothsOneDay Period.of(2,6,1);
操作、解析和格式化日期
LocalDate l1 LocalDate.of(2019, 4, 10);
LocalDate l2 l1.withYear(2020);
LocalDate l3 l2.withMonth(5);
LocalDate l4 l3.withDayOfMonth(20);
System.out.println(l1);//2019-04-10,with方法会创建对象的副本,原对象不变
System.out.println(l4);//2020-05-20像LocalDate、LocalTime、LocalDateTime以及Instant这些表示日期和时间的类提供了大量的通用方法 1、from 静态方法 依据传入的Temporal对象创建是实例
2、now 静态方法 依据系统时钟创建Temporal对象
3、of 静态方法 由Temporal对象的某个部分创建对象的实例
4、 parse 静态方法 由字符串创建Temporal对象的实例
5、atOffset 将Temporal对象和某个时区偏移相结合
6、atZone 将Temporal 对象和某个时区相结合
7、format 使用某个指定的格式将Temporal对象转换为字符串Instant类不提供此方法
8、get 读取Temporal对象的某一部分的值
9、minus 创建对象的一个副本然后将当前的Temporal对象的值减去一定的时长创建该副本
10、plus 创建对象的一个副本然后将当前Temporal对象的值加上一定的时长创建该副本
11、with 以该对象为模板对某些状态进行修改创建该对象的副本。
TemporalAdjuster精细化操作
操纵更复杂的日期比如将日期调整到下个周日、下个工作日或者是本月的最后一天。这时可以使用with的重载版本向其传递一个提供了更多定制化选择的TemporalAdjuster对象更加灵活的处理日期。
import static java.time.temporal.TemporalAdjusters.*;LocalDate dd LocalDate.of(2018,8,23);LocalDate dd1 dd.with(dayOfWeekInMonth(2,DayOfWeek.FRIDAY)); //同一个月中第二个星期五 2018-08-10LocalDate dd2 dd.with(firstDayOfMonth()); //当月的第一天 2018-08-01
LocalDate dd3 dd.with(firstDayOfNextMonth()); //下月的第一天 2018-09-01
LocalDate dd4 dd.with(firstDayOfNextYear()); //明年的第一天 2019-01-01
LocalDate dd5 dd.with(firstDayOfYear()); //当年的第一天 2018-01-01
LocalDate dd6 dd.with(firstInMonth(DayOfWeek.MONDAY)); //当月第一个星期一 2018-08-06LocalDate dd7 dd.with(lastDayOfMonth()); //当月的最后一天 2018-08-31
LocalDate dd8 dd.with(lastDayOfYear()); //当年的最后一天 2018-12-31
LocalDate dd9 dd.with(lastInMonth(DayOfWeek.SUNDAY)); //当月最后一个星期日 2018-08-26LocalDate dd10 dd.with(previous(DayOfWeek.MONDAY)); //将日期向前调整到第一个符合星期一 2018-08-20
LocalDate dd11 dd.with(next(DayOfWeek.MONDAY)); //将日期向后调整到第一个符合星期一 2018-08-27LocalDate dd12 dd.with(previousOrSame(DayOfWeek.FRIDAY)); //将日期向前调整第一个符合星期五如果该日期已经符合直接返回该对象 2018-08-17
LocalDate dd13 dd.with(nextOrSame(DayOfWeek.FRIDAY)); //将日期向后调整第一个符合星期五如果该日期已经符合直接返回该对象 2018-08-24打印输出及解析日期
处理日期和时间对象时格式化以及解析日期-时间对象是另一个非常重要的功能。新的java.time.format包就是为了这个目的而设计的。这个包中最重要的类是DateTimeFormatter创建格式器最简单的方式是通过他的静态工厂方法及常量。
String s1 next.format(DateTimeFormatter.BASIC_ISO_DATE); //20180824
String s2 next.format(DateTimeFormatter.ISO_LOCAL_DATE); //2018-08-24
除了解析为字符串外还可以通过解析代表日期或时间的字符串重新创建该日期对象。
LocalDate date1 LocalDate.parse(20180901,DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 LocalDate.parse(2018-09-02,DateTimeFormatter.ISO_LOCAL_DATE);
与老的java.util.DateFormat想比较所有的DateTimeFormatter实例都是线程安全的。DateTimeFormatter类还支持一个静态工厂方法它按照某个特定的模式创建格式器。
DateTimeFormatter formatter DateTimeFormatter.ofPattern(dd/MM/yyyy);
LocalDate now LocalDate.now();
String formatterDate now.format(formatter);
LocalDate nowparse LocalDate.parse(formatterDate,formatter);
ofPattern可以按照指定的格式进行解析成字符串然后又调用了parse方法的重载 将该格式的字符串转换成了 LocalDate对象。 ofPattern也提供了重载版本使用它可以创建某个Locale的格式器
DateTimeFormatter formatter2 DateTimeFormatter.ofPattern(yyyy年MMMMd号, Locale.CHINA);
LocalDate chinaDate LocalDate.parse(2018-08-21);
String formatterDate2 chinaDate.format(formatter2); //2018年八月21号
LocalDate chinaDate2 LocalDate.parse(formatterDate2,formatter2);DateFormatterBuilder类还提供了更复杂的格式器和更强大的解析功能
DateTimeFormatter chinaFormatter new DateTimeFormatterBuilder().appendText(ChronoField.YEAR).appendLiteral(年).appendText(ChronoField.MONTH_OF_YEAR).appendText(ChronoField.DAY_OF_MONTH).appendLiteral(号).parseCaseInsensitive().toFormatter(Locale.CHINA);处理不同的时区和历法 之前所看到的日期和时间种类都不包含时区信息。时区的处理是新版日期和时间API新增加的重要功能新的 java.time.ZoneId 类是老版 java.util.TimeZone 的替代品。
时区是按照一定的规则将区域划分成的标准时间相同的区间。在ZoneRules这个类中包含了40个这样的实例。你可以使用ZoneId的getRules()得到指定时区的规则。每个特定的ZoneId对象都由一个地区标识
ZoneId romeZone ZoneId.of(Europe/Rome); //格式 欧洲/罗马
地区ID都为 “{区域}/{城市}”的格式这些地区集合的设定都由英特网编号分配机构IANA的时区数据库提供。你可以通过java 8的新方法toZoneId将一个老的时区对象转换为ZoneId
ZoneId zoneId TimeZone.getDefault().toZoneId();
一旦得到一个ZoneId对象就可以将它与LocalDate、LocalDateTIme或者是Instant对象整合起来构造为一个ZonedDateTime实例它代表了相对于指定时区的时间点
LocalDate date LocalDate.of(2018,8,22);
ZonedDateTime zdt1 date.atStartOfDay(romeZone);LocalDateTime dateTime LocalDateTime.of(2018,8,23,13,48,00);
ZonedDateTime zdt2 dateTime.atZone(romeZone);Instant instant Instant.now();
ZonedDateTime zdt3 instant.atZone(romeZone);
ZonedDateTime LocalDateTime(LocalDate LocalTime) ZoneId
通过ZoneId你还可以将LocalDateTime转换为Instant
LocalDateTime dateTime LocalDateTime.of(2018,8,23,13,48,00);
Instant instantFromDateTime dateTime.toInstant(romeZone);Instant instant1 Instant.now();
LocalDateTime timeFromInstant LocalDateTime.ofInstant(romeZone);
利用和 UTC/格林尼治时间的固定偏差计算时区
另一种比较常用的表达时区的方式就是利用当前时区和 UTC/格林尼治 的固定偏差比如纽约落后伦敦5小时。这种情况下你可以使用ZoneOffset类它是ZoneId的一个子类表示的是当前时间和伦敦格林尼治子午时间的差异
ZoneOffset newYorkOffset ZoneOffset.of(-05:00);
这种方式不推荐使用因为 -0500 的偏差实际上是对应的美国东部标准时间并未考虑任何日光时的影响。
LocalDateTime dateTime1 LocalDateTime.now();
OffsetDateTime dateTimeInNewYork1 OffsetDateTime.of(dateTime1,newYorkOffset);它使用ISO-8601的历法系统以相对于UTC时间的偏差方式表示日期时间。
使用别的日历系统
ISO-8601日历系统是世界文明日历系统的事实标准。但是java 8 中另外提供了4种其他的日历系统。这些日历系统中的每一个都有一个对应的日志类分别是ThaiBuddhistDate、MinguoDate、JapaneseDate以及HijrahDate。所有这些类以及LocalDate都实现了ChronoLocalDate接口能够对公历的日期进行建模。利用LocalDate对象可以创建这些类的实例。
小结
Java 8之前的java.util.Date类以及其他用于建模日期时间的雷有很多不一致及设计上的缺陷包括易变性以及糟糕的偏移值、默认值和命名新版的日期和时间API中日期-时间对象是不可变的操纵的日期不会影响老值而是新生成一个实例新的API提供了两种不同的时间表示方式有效地区分了运行时人和机器的不同需求TemporalAdjuster可以更精确的操纵日期还可以自定义日期转换器他们都是线程安全的
参考 新API的用法 https://www.cnblogs.com/baidawei/p/9519747.html https://blog.csdn.net/zsx157326/article/details/80887673 https://blog.csdn.net/w592376568/article/details/80408742
旧API https://blog.csdn.net/quxing10086/article/details/80032713 https://www.cnblogs.com/CSU-PL/p/4430787.html