JAVA8新特性指路:
0.理解代码参数化和函数式编程
1.全新的时间API
2. optinal的用法
3. lambda表达式
4.Stream流
java8的 java.time API
秒的定义:
是地球完成一次自转的86400分之一,但是地球自传时间并不完全不变,所以秒,需要更精确的定义,在1967年,秒被定义为,铯133原子的固有属性定义出秒,此后官方时间根据原子钟网络同步。
问题:绝对时间需要与地球自转同步,从1972年喀开始,采取的措施改为插入“闰秒”,这样一天就并非为86400秒了
JAVA时间规范:
//时间线德一个点 从1970-01 00:00:00 作为起点
Instant now= Instant.now();
System.out.println(now);
Instant nextDay=now.plus(1, ChronoUnit.DAYS);
Duration dayDuration=Duration.between(now,nextDay);
System.out.println(dayDuration);
System.out.println(dayDuration.toDays());
System.out.println(dayDuration.toHours());
System.out.println(dayDuration.toMinutes());
System.out.println(dayDuration.toMillis());
Millis());
System.out.println(dayDuration.toNanos());
本地日期的理解: 对于各个不同地区的人来说,日常没有时区的概念,而且对于各个时区的人来说,每年都是一样得365/366个日期。所以如果不是确定不同时区的同一时间点,一般不需要使用时区这一概念。
通过LocalDate.now() 可获得不包含时区的本地日期。为了确定本地的日期创建LocalDate需要当前的时区信息才能初始化。如果不指定,则是根据操作系统确定。Clock.systemDefaultZone()
LocalDate now = LocalDate.now();
now=LocalDate.now(Clock.systemDefaultZone());
指定年月日来手动创建,localDate 抛弃了UNIX时间系统中,从0开始的反人类做法,月份从1开始。月份信息除了用数字,也可以用月份的枚举表示-java.time.Month
LocalDate birthday=LocalDate.of(1998,1,6);
birthday=LocalDate.of(1998, Month.JANUARY,6);
方法 | 描述 |
---|---|
now、of | 静态方法,获取LocalDate实例 |
plusDays,plusWeek,plusMonth,plusYear | 为当前LocalDate对象,增加年月日周 |
minusDays,minusWeek,minusMonth,minusYear | 为当前LocalDate对象,减去年月日周 |
plus,minus | 添加或者减少一个Duration或Period |
withDayOfMonth,withDayOfYear,withMonth,withYear | 将月份、天数、年份、修改为指定的值,并且返回一个新的LocalDate对象 |
with | 传入TemporalAdjuster 来调整时间。LocalDate也是TemporalAdjuster 的实现类。其实是对当前Temporal使用TemporalAdjuster的adjustInto方法 |
adjustInto | 传入 Temporal对象(例如LocalDate) 继承自TemporalAdjuster 的方法,将传入的对象,调整为和当前对象一样的日期。大多数情况下用反转调用模式With方法 更清楚。 |
getDayOfMonthgetDayOfYeargetDayOfWeek | 返回月份的天数返回年份的天数返回星期返回一个DayOfWeek的枚举值 |
getMonth、getMonthValue | 获取当前月份、返回1-12的整形,或者Month枚举 |
getYear | 获取年份-9999999999~999999999 |
Util | 获取两个日期之间的Period周期,或者指定ChronoUnits,返回整形。 |
isBefore、isAfter | 比较两个日期哪个更早 |
isLeapYear | 按照能被4或者400整除,但不能被100整除 判断是否是闰年。返回布尔值 |
LocalDate的距离类似时间线上的Duration
有些时候,直接使用Duration可能并不准确,对于并不确定时长的时间例如 月份(不同月的月份和相同的月份对应的Duration有可能不相同)
Period存储的结果,包含了年相差的数字 月相差的数字 日相差的数字
Peroid可以由两个LocalDate得出差值,也可以使用其预定义的of方法来生成
//生成Period
//其预定义的方法
birthday.plus(Period.ofYears(1));
//上方LocalDate的plus(Duration/Peroid) 等效下方
birthday.plusYears(1);
//LocalDate的until方法能快速计算两个本地日期之间的距离 计算本身到目标日期的时间距离。
LocalDate christmas=LocalDate.of(2021,12,25);
//period可以理解为 now 加上多少年 加上多少月 再加上多少天 正好等于christmas
Period period= now.until(christmas);
Peroid对象,可以分别获取其包含的 年月日的差值但是并不常用,因为无法衡量差距的具体时间长度
Peroid可以转化为指定的的** TemporalUnit(实现类为ChronoUnits)**
Peroid也可以进行加减调整
Period period= now.until(christmas);
//间隔的年月都无法得到准确的天数,所以一般不常用。
System.out.println(period.getYears()+"年 "+period.getMonths()+"月 "+period.getDays());
//获取period的天数
System.out.println(now.until(christmas,ChronoUnit.DAYS));
System.out.println(period.get(ChronoUnit.DAYS));
介绍
TemporalAdjuster
TemporalAdjuster是一个函数式接口 Temporal adjustInto(Temporal temporal);
Locadate也实现了TemporalAdjuster,作用是将传入的日期调整到和当前对象同样的日期相当于使用Temporal.with(TemporalField, long)传递ChronoField.EPOCH_DAY作为字段更推荐使用with方法。
public LocalDate with(TemporalAdjuster adjuster) {
// optimizations
if (adjuster instanceof LocalDate) {
return (LocalDate) adjuster;
}
return (LocalDate) adjuster.adjustInto(this);
}
自定义TemporalAdjuster的时候,表达式参数类型为 Temporal,如果需要用于LocalDate则需要进行强制转换。可以使用TemporalAdjusters.UnaryOperator() 来避免强制转换。
方法 | 描述 |
---|---|
now、of | 创建LocaTime实例的静态方法 |
plusHours、plusMinutesplusSeconds、plusNanos | 向当前LocalTime对象添加几小时、几分钟、几秒钟、几微秒 |
minusHours、minusMinutesminusSeconds、minusNanos | 向当前LocalTime对象减去几小时、几分钟、几秒钟、几微秒 |
plus、minus | 当前LocalTime增加或减少指定的时间单位的时间 |
winthHour、withMinutewithSecond、withNano | 单独调整某个时间单位至制定的值 |
getHour,getMinutegetSecond,getNano | 单独获取某个时间部位的值 |
toSecondOfDaytoNanoOfDay | 返回从零点开始,至当前时间经过的秒数或者微秒数 |
isBefore、isAfter | 两个LocaTime进行比较 |
由于地球的自传公转决定了,我们生活在地球上,无法完全按照同一个时间来安排生活和社会活动。否则的话,可能有人在12:00吃午饭,但是对于另一地区来说,他们可能02:00 才对应着真正的太阳直射时间。
所以人们便自己创建了时区机制、来保证能更合理的安排生产生活。时区机制,比自传公转这些问题更加复杂。目前世界时区的数据库,由因特网编号管理局(Interent Assigned Number Authority) IANA 来维护,每年会更新几次,来处理夏令时规则的变化。JAVA便是使用了IANA的数据库。
什么是夏令时: 夏令时一般是在昼长夜短的夏季,人为的将时钟拨快一小时。假如夏天5点天亮,如果作息习惯不变,按照原来的习惯,早上6点关灯的话,就浪费了一小时的电量。所以当夏天来临,就实行夏令时机制,将始终拨快,这样的话,原本五点天亮,六点关灯,就变成了,五点天亮,五点关灯,因为始终拨快后的六点,便对应着原来的五点了。
我国停止使用夏令时: 我们在1986年开始使用夏令时,在1991年宣布不再使用。夏令时有种掩耳盗铃的意味,在不同的季节,调整作息时间比起粗暴的波动时针可能更合理 1、夏令时相当于强制改变人的作息习惯 2、夏令时造成某些时间出现两次极其混乱 3、我国横跨五个时区,夏令时并不够通用 4、节约的照明电量有限,反而会增加制冷耗电
GMT (Greenwich Mean Time) 格林威治标准时,用标准世界时UTC表示则为UTC+0
CST
//1、获取当前所有的时区ID 大约600个
Set<String> availableZoneId = ZoneId.getAvailableZoneIds();
//2、根据时区ID获取ZoneId对象,ZoneId对象能用来初始化TimeZone
ZoneId GMT= ZoneId.of("GMT");
TimeZone timeZone= TimeZone.getTimeZone(GMT);
System.out.println(timeZone);
//3、LocaDateTime能通过atZone(zoneid) 来转化为 ZoneDateTime
LocalDateTime currentTime=LocalDateTime.now();
System.out.println("本地时区时间:"+currentTime);
System.out.println("GMT带时区时间:"+currentTime.atZone(GMT));
//4、通过手动设置日期、时间、时区来初始化 ZoneDateTime
ZonedDateTime zonedDateTime=ZonedDateTime.of(2021,11,28,01,34,00,0,ZoneId.systemDefault());
//5、带时区的时间点都是可以转化为一个Instant对象的,Instant对象也可以转换为对应的时区的时间
Instant instant=zonedDateTime.toInstant();
ZonedDateTime zonedDateTime1=instant.atZone(GMT);
//2021-11-28T01:34+08:00[Asia/Shanghai]
System.out.println(zonedDateTime);
//2021-11-27T17:34Z[GMT]
System.out.println(zonedDateTime1);
ZonedDateTime 和 LocalDateTime 中的方法几乎一样,而且意义都显而易见。只是夏令时带来了一些复杂性。
方法 | 描述 |
---|---|
now、of、ofInstant | 创建一个ZonedDateTime |
plusXXX例如 :Day、Weeks、Months、Years、Hours、minutes、Seconds、Nanos | 添加对应时间单位的时间 |
minusXXX例如 :Day、Weeks、Months、Years、Hours、minutes、Seconds、Nanos | 从当前时间减去对应时间单位的时间 |
plus、minus | 添加或者减少一个Duration 或者Period |
withDayOfMonth,withDayOfYear,withMonth,withYear,winthHour、withMinutewithSecond、withNano | 单独调整对应时间单位的值,返回新的ZonedDateTime |
withZoneSameInstantwithZoneSameLocal | 获取同一个时间点的另一个时区的ZonedDateTime或者获取同一个本地时间,不同时间点的另一个时区的ZonedDateTime |
getDayOfMonth getDayOfYeargetDayOfWeek | 获取131之间的月份中的第几天获取1366一年中的天数获取星期几 或者DayOfWeek枚举 |
getMonth、getMonthValue | 获取月份 或者获取Month的枚举 |
getYear | 获取年份 |
getHour 、Minute、Second、Nano | 获取时间信息 |
getOffset | 获取对应时间点对应的时区的偏移量因为对应地区的时区信息并不是简单地,GMT+n UTC+n ,往往还涉及历史原因或者夏令时制度,所以不同时间点的偏移量是不一样的。一般在-12:00 至 +14之间,涉及夏令时可能还有分钟的区别 |
toLocalDate 、toLocalTime、toInstant | 转换为本地时间、或者对应的时间点 |
isBefore isAfter | 比较两个对象 |
DateTimeFormatter 提供了三种方式来格式化日期/时间
风格 | 日期 | 时间 |
---|---|---|
SHORT | 7/16/69 | 9:32 AM |
MEDIUM | Jul 16,1969 | 9:32:00 AM |
LONG | Jul 16,1969 | 9:32:00 AM EDT |
FULL | Wendsday,Jul 16,1969 | 9:32:00 AM EDT |
LocalDate localDate=LocalDate.now();
LocalTime localTime=LocalTime.now();
ZonedDateTime zonedDateTime=ZonedDateTime.now();
//1、解析成预定义的标准化格式 2021-11-27T19:12:11.623Z
System.out.println(DateTimeFormatter.ISO_INSTANT.format(zonedDateTime));
//2、四种解析风格 SHORT、MEDIUM、LONG 、FULL
// 2021年11月28日 星期日 上午03时15分18秒 CST
DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
System.out.println(dateTimeFormatter.format(zonedDateTime));
//2021年11月28日 星期日 上午03时19分08秒 CST
dateTimeFormatter=dateTimeFormatter.withLocale(Locale.US);
//Sunday, November 28, 2021 3:19:08 AM CST
System.out.println(dateTimeFormatter.format(zonedDateTime));
LocalDate localDate=LocalDate.now();
LocalTime localTime=LocalTime.now();
ZonedDateTime zonedDateTime=ZonedDateTime.now();
//1、解析成预定义的标准化格式 2021-11-27T19:12:11.623Z
System.out.println(DateTimeFormatter.ISO_INSTANT.format(zonedDateTime));
//2、四种解析风格 SHORT、MEDIUM、LONG 、FULL
// 2021年11月28日 星期日 上午03时15分18秒 CST
DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
System.out.println(dateTimeFormatter.format(zonedDateTime));
//2021年11月28日 星期日 上午03时19分08秒 CST
dateTimeFormatter=dateTimeFormatter.withLocale(Locale.US);
//Sunday, November 28, 2021 3:19:08 AM CST
System.out.println(dateTimeFormatter.format(zonedDateTime));
//字符串转换为时间
dateTimeFormatter=DateTimeFormatter.ofPattern("世纪: GGGG 时区: zzzz YYYY年 MM月 dd 日");
//世纪: 公元 时区: 中国标准时间 2021年 11月 28 日
System.out.println(dateTimeFormatter.format(zonedDateTime));
dateTimeFormatter=dateTimeFormatter.withLocale(Locale.US);
//世纪: Anno Domini 时区: China Standard Time 2021年 11月 28 日
System.out.println(dateTimeFormatter.format(zonedDateTime));
转换的类 | To遗留类 | FROM遗留类 |
---|---|---|
Instant和Date | Date.from(instant) | data.toInstant() |
ZoneDateFormatGregorianCalendar | GregorianCalendar.from() | cal.toZoneDateTime() |
Instantjava.sql.TimeStamp | Timestamp.from | timestamp.toInstant() |
LocalDateTimejava.sql.TimeStamp | TimeStamp.valueOf(localDateTime) | timeStamp.toLocalDateTime() |
LocalDatejava.sql.Time | Date.valueOf(localDate) | data.toLocalDate() |
LocalTimejava.sql.Time | Time.valueOf(localTime) | time.toLocalTime() |
DateTimeFormatterjava.text.DateFormat | formatter.toFormat() | 无 |
java.util.TimeZoneZoneId | TimeZone.getTimeZone(zoneid) | timeZone.toZoneId() |