欢迎光临散文网 会员登陆 & 注册

日期和时间API

2023-03-13 18:05 作者:皇only胥  | 我要投稿

日期和时间API

因为时间能够和朝夕与季节挂钩,所以使得事情变得复杂。


时间线

时间单位是以秒为单位,是从地球的自转中推导出来的。地球自转一周需要24个小时,即24 x 60 x 60 = 86400秒。但是地球有轻微的颤动,所以需要更加精确的定义。

1976年,人们根据铯133原子内的特性推导出了与其历史定义相匹配的秒的新的精确定义。

Java Date和Time API 规范要求Java使用的时间尺度为:

  • 每天86400秒

  • 每天正午与官方时间精确匹配

  • 在其他时间点上,以精确定义的方式与官方时间接近匹配。


在Java中,Instant表示时间线上的某个点。

被称为“新纪元”的时间线原点被设置为穿过格林威治皇家天文台的本初子午线所处时区的1970年1月1日的午夜。这与UNIX/POSIX时间中使用的惯例相同。 从该原点开始,时间按照每天86400秒向前或向回度量,精确到纳秒。

Instance的值可向回追溯到10亿年(Instant.MIN)。最大值Instant.MAX是公元1000 000 000年的12月31日。

Instant.now()会给出当前的时刻。 可以按照常用的方式,用equals和compareTo方法来比较两个Instatnt的对象,因此可以将Instant对象用作时间戳。

使用静态方法计算两个时间的时间差:Duration.between.

Instant start = Instant.now();
runAlgorithm(); // 中间计算过程
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
long millis = timeElapsed.toMillis();

Duration是两个时刻之间的时间量。 通过调用toNanos、toMIllis、getSeconds、toMinutes、toHours和toDays来获得Duration按照传统单位度量的时间长度。

Duration对象的内部存储所需的空间超过了一个long值,因此秒数存储在一个long中,而纳秒数存储在一个额外的int中。如果想要让计算精确到纳秒级,那么就需要整个Duration的存储内容。 如果不要求那么高的精度,可以用long值来执行计算,然后直接调用toNanos。

注意:大约300年时间对应的纳秒数才会溢出long的范围。

例如:检测某个算法是否比另一个算法快10倍。

Duration timeElasped2 = Duration.between(start2, end2);
boolean overTenTimesFaster =
   timeElasped.multipliedBy(10)*minus(timeElapsed2).isNegative();
// or timeElasped.toNanos() * 10 < timeElapsed2.toNanos();

用于时间的Instant和Duration的算术运算

方法描述plus、minus在当前的Instant或Duration上加上或减去一个DurationplusNanos、plusMillis、plusSeconds、minusNanos、minusMillis、minusSeconds在当前的Instant或Duration上加上或减去给定时间单位的数值    plusMinutes、plusHours、plusDays、minusMinutes、minusHours、minusDays在当前Duration上加上或减去给定时间单位的数值multipliedBy、dividedBy、negated返回由当前Duration乘以或除以给定long或-1而得到的Duration。注意,可以缩放Duration,但是不能缩放InstantisZero、isNegative检查当前的Duration是否是0或负值

注意:Instant和Duration类都是不可修改的类,所以诸如multipliedBy和minus这样的方法都会返回一个新的实例。


本地时间

Java API包含两种人类时间, 本地日期/时间 和时区时间。

本地日期/时间包含日期和当天的时间,但是与时区信息没有任何关联。

例如:2023年3月13日 就是一个本地日期。 因为这个日期既没有当前的时间,也没有时区信息,因此不对应精确的时刻。

例如:2023年3月13日 17:09:00 Asia/Shanghai 是一个时区日期/时间,表示的是时间线上的一个精确的时刻。


某些情况下,时区甚至是一个障碍。例如安排每周10:00开一次会议。 如果加7天(即7×24×60×60秒)到最后一次会议的时区时间上,可能会碰巧跨越夏令时的时间调整边界,这次会议可能会早一个小时或晚一个小时。

除非确实想要表示绝对时间的实例,不推荐使用时区时间。 生日、假日、计划时间等通常最好都表示成本地日期和时间。


LocalDate是带有年、月、日的日期。

LocalDate today = LocalDate.now();
LocalDate alonzosBirthday = LocalDate.of(1903, 6, 14);
alonzosBirthday = LocalDate.of(1903, Month.JUNE, 14);
// 可以使用Month的枚举类型

LocalDate的方法

方法描述now, of构建一个LocalDate,要么从当前时间构建,要么从给定的年月日构建。plusDays,plusWeeks,plusMonths,plusYears在当前的LocalDate上加上一定量的天、星期、月或年minusDays,minusWeeks,minusMonths,minusYears在当前的LocalDate上减去一定量的天、星期、月或年plus、minus加上或减去一个Duration或PeriodwithDaysOfMonth,withDayOfYear,withMonth,withYear返回一个新的LocalDate,其月的日期、年的日期、月或年修改为给定的值getDayOfMonth获取月的日期(在1到31之间)getDayOfYear获取年的日期(在1到366之间)getDayOfWeek获取星期日期,返回DayOfWeek枚举值getMonth,getMonthValue获取月份的Month枚举值,或者是1 ~ 12之间的数字getYear获取年份,在-999 999 999到999 999 999之间until获取Period,或者两个日期之间按照给定的ChronoUnits计算的数值isBefore,isAfter将当前的LocalDate与另一个LocalDate进行比较isLeapYear如果当前是闰年,则返回true。即,该年份能够被4整除,但是不能被100整除,或者能够被400整除。该算法可以应用于已经过去的年份,尽管在历史上并不准确。

例如每年的第256天使程序员日。

LocalDate day = LocalDate.of(2023, 1, 1).plusDays(255);

两个Instant之间的时长是Duration,用于本地日期的等价物是Period,它表示的是流逝的年、月或日的数量。可以调用birthday.plus(Period.ofYears(1))获取下一年的生日。 也可以直接调用birthday.plusYears(1)。但是birthday.plus(Duration.ofDays(365))在闰年是错误的结果。


util方法:产生两个本地日期之间的时长: independenceDay.util(christmas),可以产生5个月21天的一段时长。确定一共有多少天,可以使用:independenceDay.util(christmas, ChronoUnit.DAYS);


警告:上述表中有些方法可能会创建并不存在的日期。例如:在1月31日加上1个月,不应该产生2月31日。这些方法并不会抛出异常,而是会返回该月有效的最后一天。

getDayOfWeek方法:产生星期日期,即DayOfWeek枚举的某个值。DayOfWeek.MONDAY的枚举值是1。

例如:LocalDate.of(1900, 1, 1).getDayOfWeek().getValue()返回1.

DayOfWeek枚举具有便捷方法plus和minus,以7为模型计算星期日期。

例如,DayOfWeek.SATURDAY.plus(3)会产生DayOfWeek.TUESDAY。

注意:周末实际上在每周的末尾。这与java.util.Calendar有所差异,在后者,星期六的值为1,而星期


日期和时间API的评论 (共 条)

分享到微博请遵守国家法律