卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法( 六 )


1ZoneRules usaRules = ZoneId.of("America/Chicago").getRules();2LocalDateTime chinaTime = //中国过去的某个时间;可是遗憾的是 , 我们不能用中国的当地时间去获取芝加哥对应时候的时间偏移量 。 因为中国的时间是按中国的偏移量算出来的哦 。 那怎么办呢?方法还是有的 。 有一点一定要记清楚 , 就是在某一瞬间 , 虽然全球时间各不一样 , 但是经过的“毫秒数”却都是一样的 。 所以先把中国过去的这个时间转化为“毫秒数” , 或者说转化为那一瞬间 , 然后再用这一瞬间去获取芝加哥在这一瞬间的时间偏移量 。 因为这一瞬间是全球都一样的 。 首先用中国的变换规则获取中国过去那个时间的偏移量 , 因为从时间到瞬间的变换需要知道时间偏移量 。 因为不知道时间偏移量的话 , 我们无法确定这个时间是哪里的时间 , 可能是现在东8区的时间 , 也可能是1个小时前东9区的时间 , 还可能是1个小时后东7区的时间 。 我去 , 好麻烦啊 , 先用中国变换规则和中国时间计算出那一瞬间吧 , 像这样子:
1ZoneRules chinaRules = ZoneId.of("Asia/Shanghai").getRules();2ZoneOffset chinaOffset = chinaRules.getOffset(chinaTime);3Instant instant = chinaTime.toInstant(chinaOffset);算出的这个瞬间instant是世界通用的 , 然后用它去计算芝加哥在这一瞬间的时间偏移量 , 像这样子:
1ZoneRules usaRules = ZoneId.of("America/Chicago").getRules();2ZoneOffset usaOffset = usaRules.getOffset(instant);现在事情已经明朗了 , 待转换的时间 , 转换前时间偏移量 , 转换后时间偏移量这三者都有了 , 就变成一个确定的情况了 。 方法和一开始用的是一样的 , 像这样子:
1ZoneOffsetTransition china2usa = ZoneOffsetTransition.of(chinaTime, chinaOffset, usaOffset);2china2usa.getDateTimeBefore();3china2usa.getDateTimeAfter();现在终于可以说一句 , 时区不是颇为复杂 , 而是相当复杂啊 。 时间系统的常用类揭秘对系统默认时区的获取依然是依赖TimeZone这个很早期的类 , 如下图04:
卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法使用这个默认的时区获取系统默认时钟 , 如下图05:
卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法在默认时钟里其实就是获取了当前经过的毫秒数 , 还是用的老方法 , 如下图06:
卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法至此 , 毫秒数和时区都已经具备 , 一个具体的时间就此产生了 。 这不就是Java时间系统的原理嘛!LocalDate类揭秘 , 先看它的存储字段 , 如下图07:
卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法只存储年/月/日三个字段 。 系统当前日期的获取方法 , 就是用系统当前默认时钟 , 算出来的 , 如下图08:
卜娃娃|最硬核的「Java8时间系统」设计原理与使用方法算法也简单 , 从时钟里取出经过的秒数和时区偏移量对应的秒数 , 加起来 , 然后再转换为天数 。 这就是自1970年1月1日起经过的天数 , 然后再计算出具体日期即可 , 如下图09: