内容简介:Java的API提供了很多有用的组件,能帮助你构建复杂的应用。不过,Java API也不总是完美的。我们相信大多数有经验的程序员都会赞同Java 8之前的库对日期和时间的支持就非常不理想。然而,你也不用太担心:Java 8中引入全新的日期和时间API就是要解决这一问题。让我们从探索如何创建简单的日期和时间间隔入手。 java.time 包中提供了很多新的类可以帮你解决问题,它们是 LocalDate 、 LocalTime 、 Instant 、 Duration 和 Period 。LocalDate 类
Java的API提供了很多有用的组件,能帮助你构建复杂的应用。不过,Java API也不总是完美的。我们相信大多数有经验的 程序员 都会赞同 Java 8之前的库对日期和时间的支持就非常不理想。然而,你也不用太担心:Java 8中引入全新的日期和时间API就是要解决这一问题。
1 LocalDate 、 LocalTime 、 Instant 、 Duration 以及 Period
让我们从探索如何创建简单的日期和时间间隔入手。 java.time 包中提供了很多新的类可以帮你解决问题,它们是 LocalDate 、 LocalTime 、 Instant 、 Duration 和 Period 。
1.1 LocalDate 和 LocalTime
LocalDate 类,该类的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息。另外,它也不附带任何与时区相关的信息。
你可以通过 静态工厂方法 of 创建一个 LocalDate 实例 。 LocalDate 实例提供了多种方法来读取常用的值,比如年份、月份、星期几等。
public static void main(String[] args) { //2014-3-18 LocalDate date = LocalDate.of(2014, 3, 18); //2014 int year = date.getYear(); //march Month month = date.getMonth(); //18 int day = date.getDayOfMonth(); DayOfWeek dow = date.getDayOfWeek(); //这个月的天数 int len = date.lengthOfMonth(); //是否事闰年 boolean leap = date.isLeapYear(); System.out.println("year : " + year + " month : " + month + " day : " + day + " dow : " + dow + " len : " + len + " leap : " + leap); } 复制代码
似地,一天中的时间,比如13:45:20,可以使用 LocalTime 类表示。你可以使用 of 重载的两个工厂方法创建 LocalTime 的实例。第一个重载函数接收小时和分钟,第二个重载函数同时还接收秒。同 LocalDate 一样, LocalTime 类也提供了一些 getter 方法访问这些变量的值。
LocalTime time = LocalTime.of(13, 45, 20); int hour = time.getHour(); int minute = time.getMinute(); int second = time.getSecond(); 复制代码
LocalDate 和 LocalTime 都可以通过解析代表它们的字符串创建。使用静态方法 parse ,你可以实现这一目的:
LocalDate date = LocalDate.parse("2014-03-18"); LocalTime time = LocalTime.parse("13:45:20"); 复制代码
1.2 合并日期和时间
这个复合类名叫 LocalDateTime ,是 LocalDate 和 LocalTime 的合体。它同时表示了日期和时间,但不带有时区信息,你可以直接创建,也可以通过合并日期和时间对象构造。
// 2014-03-18T13:45:20 LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(13, 45, 20); LocalDateTime dt4 = date.atTime(time); LocalDateTime dt5 = time.atDate(date); 复制代码
通过它们各自的 atTime 或者 atDate 方法,向 LocalDate 传递一个时间对象,或者向LocalTime 传递一个日期对象的方式,你可以创建一个 LocalDateTime 对象。你也可以使用toLocalDate 或者 toLocalTime 方法,从 LocalDateTime 中提取 LocalDate 或者 LocalTime组件:
LocalDate date1 = dt1.toLocalDate(); LocalTime time1 = dt1.toLocalTime(); 复制代码
1.3 Duration 和 Period
Duration 类的静态工厂方法 between 就是为比较两个时间而设计的。你可以创建两个 LocalTimes 对象、两个 LocalDateTimes对象,或者两个 Instant 对象之间的 duration:
Duration d1 = Duration.between(time1, time2); Duration d1 = Duration.between(dateTime1, dateTime2); 复制代码
如果你需要以年、月或者日的方式对多个时间单位建模,可以使用 Period 类。使用该类的工厂方法 between ,你可以使用得到两个 LocalDate 之间的时长:
Period tenDays = Period.between(LocalDate.of(2014, 3, 8), LocalDate.of(2014, 3, 18)); 复制代码
最后, Duration 和 Period 类都提供了很多非常方便的工厂类,直接创建对应的实例;换句话说,就像下面这段代码那样,不再是只能以两个temporal对象的差值的方式来定义它们的对象。
Duration threeMinutes = Duration.ofMinutes(3); Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES); Period tenDays = Period.ofDays(10); Period threeWeeks = Period.ofWeeks(3); Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1); 复制代码
Duration 类和 Period 类共享方法
2 操纵、解析和格式化日期
2.1 比较直观的方式操纵 LocalDate 的属性
//2019-3-20 LocalDate of = LocalDate.of(2019, 3, 20); //2018-3-20 LocalDate localDate = of.withYear(2018); //2018-4-20 LocalDate localDate1 = localDate.withMonth(4); //2018-9-20 LocalDate with = localDate1.with(ChronoField.MONTH_OF_YEAR, 9); 复制代码
最后这一行中使用的 with 方法和get方法有些类似,它们都声明于 Temporal 接口,所有的日期和时间API类都实现这两个方法,它们定义了单点的时间,比如 LocalDate 、 LocalTime 、 LocalDateTime 以及 Instant 。更确切 地说,使用 get 和 with 方法,我们可以将 Temporal 对象值的读取和修改区分开。
2.2 以相对方式修改 LocalDate 对象的属性
//2014-3-18 LocalDate date1 = LocalDate.of(2014, 3, 18); //2014-3-25 LocalDate date2 = date1.plusWeeks(1); LocalDate date3 = date2.minusYears(3); LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); 复制代码
最后一行使用的 plus 方法也是通用方法,它和 minus 方法都声明于 Temporal 接口中。通过这些方法,对 TemporalUnit 对象加上或者减去一个数字,我们能非常方便地将 Temporal 对象前溯或者回滚至某个时间段,通过ChronoUnit 枚举我们可以非常方便地实现 TemporalUnit 接口。
2.3 使用 TemporalAdjuster
有的时候,你需要进行一些更加复杂的操作,比如,将日期调整到下个周日、下个工作日,或者是本月的最后一天。这时,你可以使用重载版本的 with 方法,向其传递一个提供了更多定制化选择的 TemporalAdjuster 对象,更加灵活地处理日期。对于最常见的用例,日期和时间API已经提供了大量预定义的TemporalAdjuster 。你可以通过 TemporalAdjuster 类的静态工厂方法访问它们。
//2014-03-18 LocalDate date1 = LocalDate.of(2014, 3, 18); //2014-03-23 LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY)); //2014-03-31 LocalDate date3 = date2.with(lastDayOfMonth()); 复制代码
正如我们看到的,使用 TemporalAdjuster 我们可以进行更加复杂的日期操作,而且这些方 法的名称也非常直观,方法名基本就是问题陈述。此外,即使你没有找到符合你要求的预定义的 TemporalAdjuster ,创建你自己的 TemporalAdjuster 也并非难事。实际上, Temporal- Adjuster 接口只声明了单一的一个方法(这使得它成为了一个函数式接口)。
@FunctionalInterface public interface TemporalAdjuster { Temporal adjustInto(Temporal temporal); } 复制代码
这意味着 TemporalAdjuster 接口的实现需要定义如何将一个 Temporal 对象转换为另一个 Temporal 对象。你可以把它看成一个 UnaryOperator
2.4 实现一个定制的 TemporalAdjuster
设计一个 NextWorkingDay 类,该类实现了 TemporalAdjuster 接口,能够计算明天的日期,同时过滤掉周六和周日这些节假日。格式如下所示:
public class MyTemporalAdjuster { public static void main(String[] args) { LocalDate of = LocalDate.of(2019, 3, 20); LocalDate with = of.with(new NewTemporalAdjuster()); System.out.println("with = " + with); } } //如果当天的星期介于周一至周五之间,日期向后移动一天;如果当天是周六或者周日,则返回下一个周一 class NewTemporalAdjuster implements TemporalAdjuster { @Override public Temporal adjustInto(Temporal temporal) { DayOfWeek of = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK)); int dayToAdd = 1; if (of == DayOfWeek.FRIDAY){ dayToAdd = 3; }else if (of == DayOfWeek.SATURDAY){ dayToAdd = 2; } return temporal.plus(dayToAdd, ChronoUnit.DAYS); } } 复制代码
2.5 打印输出及解析日期--时间对象
处理日期和时间对象时,格式化以及解析日期时间对象是另一个非常重要的功能。新的java.time.format 包就是特别为这个目的而设计的。这个包中,最重要的类是 DateTimeFormatter 。创建格式器最简单的方法是通过它的静态工厂方法以及常量。像 BASIC_ISO_DATE和 ISO_LOCAL_DATE 这 样 的 常 量 是 DateTimeFormatter 类 的 预 定 义 实 例 。 所 有 的DateTimeFormatter 实例都能用于以一定的格式创建代表特定日期或时间的字符串。
LocalDate date = LocalDate.of(2014, 3, 18); //20140318 String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); //2014-03-18 String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); 复制代码
你也可以通过解析代表日期或时间的字符串重新创建该日期对象。所有的日期和时间API都提供了表示时间点或者时间段的工厂方法,你可以使用工厂方法 parse 达到重创该日期对象的目的:
LocalDate date1 = LocalDate.parse("20140318",DateTimeFormatter.BASIC_ISO_DATE); LocalDate date2 = LocalDate.parse("2014-03-18",DateTimeFormatter.ISO_LOCAL_DATE); 复制代码
2.6 按照某个模式创建 DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); LocalDate date1 = LocalDate.of(2014, 3, 18); String formattedDate = date1.format(formatter); LocalDate date2 = LocalDate.parse(formattedDate, formatter); 复制代码
LocalDate 的 formate 方法使用指定的模式生成了一个代表该日期的字符串。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Perl语言入门
[美] Randal L.Schwartz、Tom Phoenix / 李晓峰 / 中国电力出版社 / 2002-8 / 48.00元
本书第一版于1993年问世,并从此成为畅销书。本书由Perl社区最著名、最活跃的两位成员写成,是Perl程序设计语言的精髓指南。 Perl最初只是Unix系统管理员的一个工具,在工作日里被用在无数的小任务中。从那以后,它逐步发展成为一种全功能的程序设计语言,特别是在各种计算平台上,它被用作Web编程、数据库处理、XML处理以及系统管理——它能够完成所有这些工作,同时仍然是处理小的日常工作的完......一起来看看 《Perl语言入门》 这本书的介绍吧!