Java从一开始就缺少了日期和时间的一致方法,Java 8日期时间API是核心Java API的欢迎补充。
为什么我们需要新的Java Date Time API?
在我们开始研究 Java 8 Date Time API 之前,让我们看看为什么我们需要一个新的 API。
- Java Date Time 类不一致地定义,我们在 java.util 和 java.sql 套件中都有 Date Class. 再次格式化和解析类在 java.text 套件中定义
- java.util.Date 包含日期和时间值,而 java.sql.Date 仅包含日期值. 在 java.sql 套件中有这种格式化和解析类没有任何意义。 此外,两个类都有相同的名称,这本身就是一个非常糟糕的设计 *没有明确的定义日期和时间格式,格式化和解析等类。 我们有 java.text.DateFormat 抽象类用于解析和格式化。 通常, [Sim
与日期和日历类别中定义的方法存在一些其他问题,但上述问题清楚地表明,在Java中需要一个强大的日期时间API,这就是为什么Joda Time(https://www.joda.org/joda-time/)作为Java日期时间要求的质量替代品发挥了关键作用。
Java 8 日期时间设计原则
Java 8 Date Time API 是 JSR-310的实现,旨在克服传统日期时间实现的所有缺陷。
- 联合国 ** Immutable**:新日期-时间 API中的所有课程都是不可改变的,对多线性环境都有好处.
- ** 关注分离**:新的API明确区分了人可读的日期时间和机器时间(Unix timestamp). 它定义了日期、时间、日期、时间、时间戳、时区等不同的类别(_) (英语). ** Classary**:方法有明确的定义,在所有类别中执行相同的动作。 例如,为了获得当前实例,我们有_Now()方法。 所有这些类别中都有定义的格式()和剖析()方法,而不是为它们另设一个类别。 () ) 所有班级都使用事实图案和战略图案来更好地处理. 一旦您在其中一个班级使用过这些方法, 与其他班级一起工作就不会有困难。 4。 ** 效用作业**: 所有新的 Date-Time API 类都带有执行共同任务的方法,比如加,减,格式,解析,在日期/时间中获得单独的部分等
- ** 可扩展**:新的日期时间API在ISO-8601日历系统上工作,但也可以与其他非ISO日历一起使用. ( (英语)
时间 API 包
Java 8 Date Time API 由以下套件组成。
- 联合国 java.time: 这是新的Java Date Time API的基础包. 所有主要的基班都是这个包的一部分,如"本地数据"(localDate),"本地时间"(localDate Time),"即时"(Instant),"时段"(perient),"持续"等. 所有这些课程都是不可改变和无线的。 在大多数情况下,这些课程将足以满足共同要求。 ( )2. **java.time.chrono **: . 这个包定义了非ISO日历系统的通用API. 我们可以扩展抽象纪事类来创建自己的日历系统.
- java.time.format: 此软件包包含用于格式化和解析日期- 时间对象的类 。 多数时候,我们不会直接使用它们,因为java中的原则课。 时间包提供格式和解析方法.
- java.time.timperal: 这个包包含了时间对象,我们可以利用它来找出与日期/时间对象相关的具体日期或时间. 例如,我们可以用这些来发现月份的第一天或最后一天. 您可以轻松识别这些方法,因为它们总是有"与XXX"的格式. (_) (英语). 5. java.time.zone (英语). 软件包: 本套件包含支持不同时区及其规则的类. ( (英语)
Java 8 日期时间 API 类示例
我们已经研究了Java Date Time API中的大多数重要部分,现在是时候用示例研究最重要的Date Time API类。
一、本地化
LocalDate 是一个不可变的类,它代表日期,默认格式为 yyyy-MM-dd. 我们可以使用 now() 方法获取当前日期. 我们还可以为年、月和日期提供输入参数,以创建 LocalDate 实例。
此类为 now() 提供了过载的方法,我们可以通过 ZoneId 获取特定时区的日期,此类提供与 java.sql.Date 相同的功能。
1package com.journaldev.java8.time;
2
3import java.time.LocalDate;
4import java.time.Month;
5import java.time.ZoneId;
6
7/**
8 * LocalDate Examples
9 * @author pankaj
10 *
11 */
12public class LocalDateExample {
13
14 public static void main(String[] args) {
15
16 //Current Date
17 LocalDate today = LocalDate.now();
18 System.out.println("Current Date="+today);
19
20 //Creating LocalDate by providing input arguments
21 LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1);
22 System.out.println("Specific Date="+firstDay_2014);
23
24
25 //Try creating date by providing invalid inputs
26 //LocalDate feb29_2014 = LocalDate.of(2014, Month.FEBRUARY, 29);
27 //Exception in thread "main" java.time.DateTimeException:
28 //Invalid date 'February 29' as '2014' is not a leap year
29
30 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
31 LocalDate todayKolkata = LocalDate.now(ZoneId.of("Asia/Kolkata"));
32 System.out.println("Current Date in IST="+todayKolkata);
33
34 //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
35 //LocalDate todayIST = LocalDate.now(ZoneId.of("IST"));
36
37 //Getting date from the base date i.e 01/01/1970
38 LocalDate dateFromBase = LocalDate.ofEpochDay(365);
39 System.out.println("365th day from base date= "+dateFromBase);
40
41 LocalDate hundredDay2014 = LocalDate.ofYearDay(2014, 100);
42 System.out.println("100th day of 2014="+hundredDay2014);
43 }
44
45}
LocalDate 方法的解释是在评论中提供的. 当我们运行这个程序时,我们得到以下输出。
1Current Date=2014-04-28
2Specific Date=2014-01-01
3Current Date in IST=2014-04-29
4365th day from base date= 1971-01-01
5100th day of 2014=2014-04-10
2、本地时间
LocalTime 是一个不可变的类,其实例代表人类可读格式中的时间,其默认格式是 hh:mm:ss.zzz. 与 LocalDate 一样,这个类提供时区支持,并通过将小时、分钟和秒作为输入参数来创建实例。
1package com.journaldev.java8.time;
2
3import java.time.LocalTime;
4import java.time.ZoneId;
5
6/**
7 * LocalTime Examples
8 * @author pankaj
9 *
10 */
11public class LocalTimeExample {
12
13 public static void main(String[] args) {
14
15 //Current Time
16 LocalTime time = LocalTime.now();
17 System.out.println("Current Time="+time);
18
19 //Creating LocalTime by providing input arguments
20 LocalTime specificTime = LocalTime.of(12,20,25,40);
21 System.out.println("Specific Time of Day="+specificTime);
22
23
24 //Try creating time by providing invalid inputs
25 //LocalTime invalidTime = LocalTime.of(25,20);
26 //Exception in thread "main" java.time.DateTimeException:
27 //Invalid value for HourOfDay (valid values 0 - 23): 25
28
29 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
30 LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));
31 System.out.println("Current Time in IST="+timeKolkata);
32
33 //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
34 //LocalTime todayIST = LocalTime.now(ZoneId.of("IST"));
35
36 //Getting date from the base date i.e 01/01/1970
37 LocalTime specificSecondTime = LocalTime.ofSecondOfDay(10000);
38 System.out.println("10000th second time= "+specificSecondTime);
39
40 }
41
42}
出发点:**
1Current Time=15:51:45.240
2Specific Time of Day=12:20:25.000000040
3Current Time in IST=04:21:45.276
410000th second time= 02:46:40
第三节 时间
LocalDateTime 是一个不可变的日期时间对象,它代表一个日期时间,默认格式为 yyyy-MM-dd-HH-mm-ss.zzz. 它提供了使用 LocalDate 和 LocalTime 输入参数创建 LocalDateTime 实例的工厂方法。
1package com.journaldev.java8.time;
2
3import java.time.LocalDate;
4import java.time.LocalDateTime;
5import java.time.LocalTime;
6import java.time.Month;
7import java.time.ZoneId;
8import java.time.ZoneOffset;
9
10public class LocalDateTimeExample {
11
12 public static void main(String[] args) {
13
14 //Current Date
15 LocalDateTime today = LocalDateTime.now();
16 System.out.println("Current DateTime="+today);
17
18 //Current Date using LocalDate and LocalTime
19 today = LocalDateTime.of(LocalDate.now(), LocalTime.now());
20 System.out.println("Current DateTime="+today);
21
22 //Creating LocalDateTime by providing input arguments
23 LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30);
24 System.out.println("Specific Date="+specificDate);
25
26
27 //Try creating date by providing invalid inputs
28 //LocalDateTime feb29_2014 = LocalDateTime.of(2014, Month.FEBRUARY, 28, 25,1,1);
29 //Exception in thread "main" java.time.DateTimeException:
30 //Invalid value for HourOfDay (valid values 0 - 23): 25
31
32
33 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
34 LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
35 System.out.println("Current Date in IST="+todayKolkata);
36
37 //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
38 //LocalDateTime todayIST = LocalDateTime.now(ZoneId.of("IST"));
39
40 //Getting date from the base date i.e 01/01/1970
41 LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);
42 System.out.println("10000th second time from 01/01/1970= "+dateFromBase);
43
44 }
45
46}
在这三个例子中,我们已经看到,如果我们为创建日期/时间提供无效的参数,那么它会扔 java.time.DateTimeException,这是一个 RuntimeException,所以我们不需要明确捕捉它。
我们还看到我们可以通过传输ZoneId获取日期/时间数据,您可以从其JavaDoc中获取支持的ZoneId值列表。
1Current DateTime=2014-04-28T16:00:49.455
2Current DateTime=2014-04-28T16:00:49.493
3Specific Date=2014-01-01T10:10:30
4Current Date in IST=2014-04-29T04:30:49.493
510000th second time from 01/01/1970= 1970-01-01T02:46:40
4、瞬间
Instant 类用于使用机器可读时间格式工作. Instant 将日期时间存储在 unix 时刻印中。
1package com.journaldev.java8.time;
2
3import java.time.Duration;
4import java.time.Instant;
5
6public class InstantExample {
7
8 public static void main(String[] args) {
9 //Current timestamp
10 Instant timestamp = Instant.now();
11 System.out.println("Current Timestamp = "+timestamp);
12
13 //Instant from timestamp
14 Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());
15 System.out.println("Specific Time = "+specificTime);
16
17 //Duration example
18 Duration thirtyDay = Duration.ofDays(30);
19 System.out.println(thirtyDay);
20 }
21
22}
输出:
1Current Timestamp = 2014-04-28T23:20:08.489Z
2Specific Time = 2014-04-28T23:20:08.489Z
3PT720H
Java 8 日期 API 用途
大多数日期时间原理类提供各种实用方法,如加/减天,周,月,等等 有一些其他实用方法可以使用TemporalAdjuster
来调整日期并计算两个日期之间的时间。
1package com.journaldev.java8.time;
2
3import java.time.LocalDate;
4import java.time.LocalTime;
5import java.time.Period;
6import java.time.temporal.TemporalAdjusters;
7
8public class DateAPIUtilities {
9
10 public static void main(String[] args) {
11
12 LocalDate today = LocalDate.now();
13
14 //Get the Year, check if it's leap year
15 System.out.println("Year "+today.getYear()+" is Leap Year? "+today.isLeapYear());
16
17 //Compare two LocalDate for before and after
18 System.out.println("Today is before 01/01/2015? "+today.isBefore(LocalDate.of(2015,1,1)));
19
20 //Create LocalDateTime from LocalDate
21 System.out.println("Current Time="+today.atTime(LocalTime.now()));
22
23 //plus and minus operations
24 System.out.println("10 days after today will be "+today.plusDays(10));
25 System.out.println("3 weeks after today will be "+today.plusWeeks(3));
26 System.out.println("20 months after today will be "+today.plusMonths(20));
27
28 System.out.println("10 days before today will be "+today.minusDays(10));
29 System.out.println("3 weeks before today will be "+today.minusWeeks(3));
30 System.out.println("20 months before today will be "+today.minusMonths(20));
31
32 //Temporal adjusters for adjusting the dates
33 System.out.println("First date of this month= "+today.with(TemporalAdjusters.firstDayOfMonth()));
34 LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
35 System.out.println("Last date of this year= "+lastDayOfYear);
36
37 Period period = today.until(lastDayOfYear);
38 System.out.println("Period Format= "+period);
39 System.out.println("Months remaining in the year= "+period.getMonths());
40 }
41}
输出:
1Year 2014 is Leap Year? false
2Today is before 01/01/2015? true
3Current Time=2014-04-28T16:23:53.154
410 days after today will be 2014-05-08
53 weeks after today will be 2014-05-19
620 months after today will be 2015-12-28
710 days before today will be 2014-04-18
83 weeks before today will be 2014-04-07
920 months before today will be 2012-08-28
10First date of this month= 2014-04-01
11Last date of this year= 2014-12-31
12Period Format= P8M3D
13Months remaining in the year= 8
Java 8 日期解析和格式化
很常见地将日期格式格式化为不同的格式,然后对字符串进行解析以获取日期时间对象。
1package com.journaldev.java8.time;
2
3import java.time.Instant;
4import java.time.LocalDate;
5import java.time.LocalDateTime;
6import java.time.format.DateTimeFormatter;
7
8public class DateParseFormatExample {
9
10 public static void main(String[] args) {
11
12 //Format examples
13 LocalDate date = LocalDate.now();
14 //default format
15 System.out.println("Default format of LocalDate="+date);
16 //specific format
17 System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));
18 System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));
19
20
21 LocalDateTime dateTime = LocalDateTime.now();
22 //default format
23 System.out.println("Default format of LocalDateTime="+dateTime);
24 //specific format
25 System.out.println(dateTime.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss")));
26 System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));
27
28 Instant timestamp = Instant.now();
29 //default format
30 System.out.println("Default format of Instant="+timestamp);
31
32 //Parse examples
33 LocalDateTime dt = LocalDateTime.parse("27::Apr::2014 21::39::48",
34 DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss"));
35 System.out.println("Default format after parsing = "+dt);
36 }
37
38}
输出:
1Default format of LocalDate=2014-04-28
228::Apr::2014
320140428
4Default format of LocalDateTime=2014-04-28T16:25:49.341
528::Apr::2014 16::25::49
620140428
7Default format of Instant=2014-04-28T23:25:49.342Z
8Default format after parsing = 2014-04-27T21:39:48
Java Date API 继承日期时间支持
传统日期/时间类几乎在所有应用中都使用,因此必须具备后向兼容性,这就是为什么我们可以将传统类转换为新类的几个实用方法,反之亦然。
1package com.journaldev.java8.time;
2
3import java.time.Instant;
4import java.time.LocalDateTime;
5import java.time.ZoneId;
6import java.time.ZonedDateTime;
7import java.util.Calendar;
8import java.util.Date;
9import java.util.GregorianCalendar;
10import java.util.TimeZone;
11
12public class DateAPILegacySupport {
13
14 public static void main(String[] args) {
15
16 //Date to Instant
17 Instant timestamp = new Date().toInstant();
18 //Now we can convert Instant to LocalDateTime or other similar classes
19 LocalDateTime date = LocalDateTime.ofInstant(timestamp,
20 ZoneId.of(ZoneId.SHORT_IDS.get("PST")));
21 System.out.println("Date = "+date);
22
23 //Calendar to Instant
24 Instant time = Calendar.getInstance().toInstant();
25 System.out.println(time);
26 //TimeZone to ZoneId
27 ZoneId defaultZone = TimeZone.getDefault().toZoneId();
28 System.out.println(defaultZone);
29
30 //ZonedDateTime from specific Calendar
31 ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();
32 System.out.println(gregorianCalendarDateTime);
33
34 //Date API to Legacy classes
35 Date dt = Date.from(Instant.now());
36 System.out.println(dt);
37
38 TimeZone tz = TimeZone.getTimeZone(defaultZone);
39 System.out.println(tz);
40
41 GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);
42 System.out.println(gc);
43
44 }
45
46}
输出:
1Date = 2014-04-28T16:28:54.340
22014-04-28T23:28:54.395Z
3America/Los_Angeles
42014-04-28T16:28:54.404-07:00[America/Los_Angeles]
5Mon Apr 28 16:28:54 PDT 2014
6sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]
7java.util.GregorianCalendar[time=1398727734404,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=3,WEEK_OF_YEAR=18,WEEK_OF_MONTH=5,DAY_OF_MONTH=28,DAY_OF_YEAR=118,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=28,SECOND=54,MILLISECOND=404,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]
正如你可以看到的那样,传统的TimeZone
和GregorianCalendar
类 toString() 方法过于语而不是用户友好。
结论
我非常喜欢这个新的日期时间API。 一些最常用的类将是LocalDate和LocalDateTime。 很容易与新类一起工作。 并且,使用类似的方法来完成某个特定的工作,很容易找到。