热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java8DateTimeAPI

Java8Date-TimeAPI详解 了解从Java版本1.0开始就支持日期和时间,主要通过java.util.Date类。但是,Date类设计不佳。例如,Date中的月份从1开

Java 8 Date-Time API 详解

 


了解

从Java版本1.0开始就支持日期和时间,主要通过java.util.Date类。 但是,Date类设计不佳。 例如,Date中的月份从1开始,但从日期却从0开始。在JDK 1.1中使用它的许多方法已经废弃,同时java.util.Calendar被引入来接管Date中的一些功能。 这两个是处理日期和时间的主要类,直到JDK 1.7,尽管他们被认为是不足够并且不容易处理,导致许多人诉诸第三方替代品,例如Joda Time(http://joda.org)。 JDK 1.8中的新日期和时间API解决了旧API中的许多问题,并且与Joda Time API类似。



 


比较

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:



  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。



  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。



  • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。



Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:



  • Local(本地) − 简化了日期时间的处理,没有时区的问题。



  • Zoned(时区) − 通过制定的时区处理日期时间。



新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。



 


Instant类

Instant实例表示时间线上的一个点。 参考点是标准的Java纪元(epoch),即1970-01-01T00:00:00Z(1970年1月1日00:00 GMT)。 Instant类的EPOCH属性返回表示Java纪元的Instant`实例。 在纪元之后的时间是正值,而在此之前的时间即是负值。

Instant的静态now方法返回一个表示当前时间的Instant对象:

Instant now = Instant.now();

 

getEpochSecond方法返回自纪元以来经过的秒数。 getNano方法返回自上一秒开始以来的纳秒数。

Instant类的一个常用用途是用来操作时间,如以下代码所示。

import java.time.Duration;
import java.time.Instant;
public class InstantDemo1 {
public static void main(String[] args) {
Instant start = Instant.now();
// do something here
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
}

如上面代码所示,Duration类用于返回两个Instant之间时间数量的差异。



 


LocalDate类

LocalDate类只包括日期没有时间的部分。 它也没有时区。 下表显示了LocalDate中一些重要的方法。
































































方法描述
now静态方法,返回今天的日期
of从指定年份,月份和日期创建LocalDate的静态方法
getDayOfMonth, getMonthValue, getYear以int形式返回此LocalDate的日,月或年
getMonth以Month枚举常量返回此LocalDate的月份
plusDays, minusDays给LocalDate添加或减去指定的天数
plusWeeks, minusWeeks给LocalDate添加或减去指定的星期数
plusMonths, minusMonths给LocalDate添加或减去指定的月份数
plusYears, minusYears给LocalDate添加或减去指定的年数
isLeapYear检查LocalDate指定的年份是否为闰年
isAfter, isBefore检查此LocalDate是在给定日期之后还是之前
lengthOfMonth返回此LocalDate中月份的天数
withDayOfMonth返回此LocalDate的拷贝,将月份中的某天设置为给定值
withMonth返回此LocalDate的拷贝,其月份设置为给定值
withYear返回此LocalDate的拷贝,并将年份设置为给定值

LocalDate提供了各种创建日期的方法。 例如,要创建代表今天日期的LocalDate,使用静态now方法。

LocalDate today = LocalDate.now();

 

要创建代表特定年,月和日的LocalDate,使用of方法,该方法也是静态的。 例如,以下代码创建了一个代表2018年3月7日的LocalDate实例。

LocalDate date = LocalDate.of(2018, 3, 7);

 

还有一个接受java.time.Month枚举的常量作为第二个参数的of方法。 例如,下面是使用第二种方法重载构造相同日期的代码。

LocalDate date = LocalDate.of(2018, Month.MARCH, 7);

 

还有获取LocalDate的日,月或年的方法,例如getDayOfMonthgetMonthgetMonthValuegetYear。 他们都没有任何参数,并返回一个int或Month的枚举常量。 另外,还有一个get方法,它接受一个TemporalField并返回这个LocalDate的一部分。 例如,传递ChronoField.YEAR以获取LocalDate的年份部分。

int year = localDate.get(ChronoField.YEAR);

 

ChronoField是一个实现TemporalField接口的枚举,因此可以传递一个ChronoField常量来获取。 TemporalFieldChronoField都是java.time.temporal包的一部分。 但是,并非ChronoField中的所有常量都可以get获取,因为并非所有常量都受支持。 例如,传递ChronoField.SECOND_OF_DAY以引发异常。 因此,取而代之,最好使用getMonthgetYear或类似方法来获取LocalDate的组件。


此外,还有拷贝LocalDate的方法,例如plusDaysplusYearsminusMonths等等。 例如,要获取表示明天的LocalDate,可以创建一个代表今天的LocalDate,然后调用其plusDays方法。

LocalDate tomorrow = LocalDate.now().plusDays(1);

 

要获取昨天表示的LocalDate,可以使用minusDays方法。

LocalDate yesterday = LocalDate.now().minusDays(1);

 

另外,还有plusminus方法以更通用的方式获得LocalDate的拷贝。 两者都接受一个int参数和一个TemporalUnit参数。 这些方法的签名如下。

public LocalDate plus(long amountToAdd, java.time.temporal.TemporalUnit unit)
public LocalDate minus(long amountToSubtract, java.time.temporal.TemporalUnit unit)

 

例如,获得一个从今天开始前20年的LocalDate,可以使用这段代码。

LocalDate pastDate = LocalDate.now().minus(2, ChronoUnit.DECADES);

 

ChronoUnit是一个实现TemporalUnit的枚举,因此可以将ChronoUnit常量传递给plusminus方法。

LocalDate是不可变的,因此无法更改。 任何返回LocalDate的方法都返回LocalDate的新实例。

以下是使用LocalDate的例子。

import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
public class LocalDateDemo1 {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
LocalDate OneDecadeAgo= today.minus(1, ChronoUnit.DECADES);
System.out.println("Day of month: " + today.getDayOfMonth());
System.out.println("Today is " + today);
System.out.println("Tomorrow is " + tomorrow);
System.out.println("A decade ago was " + oneDecadeAgo);
System.out.println("Year : " + today.get(ChronoField.YEAR));
System.out.println("Day of year:" + today.getDayOfYear());




 


Period类

Period类基于日期的时间数量构建,例如五天,一周或三年。 下面列出了一些重要的方法。
























































方法描述
between在两个LocalDates之间创建一个Period示例
ofDays, ofWeeks, ofMonths, ofYears创建代表给定天数/周/月/年的Period实例
of根据给定的年数,月数和天数创建一个Period实例
getDays, getMonths, getYears以int形式返回此Period的天数/月/年
isNegative如果此Period的三个部分中的任何一个为负数,则返回true。 否则返回false
isZero如果此Period的所有三个部分均为零,则返回true。 否则,返回false
plusDays, minusDays在此Period上添加或减去给定的天数
plusMonths, minusMonths在此Period上增加或减去给定的月数
plusYears, minusYears在此Period增加或减去给定的年数
withDays以指定的天数返回此Period的拷贝
withMonths以指定的月数返回此Period的拷贝
withYears以指定的年数返回此Period的拷贝

创建一个Period很简单,这要感谢between,of,ofDays / ofWeeks / ofMonths / ofYears等静态工厂方法。 例如,以下是如何创建代表两周的Period实例。

Period twoWeeks = Period.ofWeeks(2);

 

要创建代表一年两个月三天的Period实例,请使用of方法。

Period p = Period.of(1, 2, 3);

 

要获取某个期间的年/月/日组件,调用其getYears / getMonths / getDays方法。 例如,以下代码中的howManyDays变量的值是14。

Period twoWeeks = Period.ofWeeks(2);
int howManyDays = twoWeeks.getDays();

 

最后,可以使用plusXXXminusXXX方法以及withXXX方法来创建Period的拷贝。 Period是不可变的,所以这些方法返回新的Period实例。

例如,下面的代码显示了一个计算个人年龄的年龄计算器。 它从两个LocalDate创建一个Period并调用它的getDaysgetMonthsgetYears方法。

import java.time.LocalDate;
import java.time.Period;
public class PeriodDemo1 {
public static void main(String[] args) {
LocalDate dateA = LocalDate.of(1978, 8, 26);
LocalDate dateB = LocalDate.of(1988, 9, 28);
Period period = Period.between(dateA, dateB);
System.out.printf("Between %s and %s"
+ " there are %d years, %d months"
+ " and %d days%n", dateA, dateB,
period.getYears(),
period.getMonths(),
period.getDays());
}
}

 

运行PeriodDemo1类打印下面字符串。

Between 1978-08-26 and 1988-09-28 there are 10 years, 1 months and 2 days


 


LocalDateTime类

LocalDateTime类是一个没有时区的日期时间的构建。 下表显示了LocalDateTime中一些重要的方法。 这些方法类似于LocalDate的方法,以及用于修改时间部分的一些其他方法,例如在LocalDate中不可用的plusHoursplusMinutesplusSeconds
































































方法描述
now返回当前日期和时间的静态方法。
of从指定年份,月份,日期,小时,分钟,秒和毫秒创建LocalDateTime的静态方法。
getYear, getMonthValue, getDayOfMonth, getHour, getMinute, getSecond以int形式返回此LocalDateTime的年,月,日,小时,分钟或秒部分。
plusDays, minusDays给当前LocalDateTime添加或减去指定的天数。
plusWeeks, minusWeeks给当前LocalDateTime添加或减去指定的周数。
plusMonths, minusMonths给当前LocalDateTime添加或减去指定的月数。
plusYears, minusYears给当前LocalDateTime添加或减去指定的年数。
plusHours, minusHours给当前LocalDateTime添加或减去指定的小时数
plusMinutes, minusMinutes给当前LocalDateTime添加或减去指定的分钟数
plusSeconds, minusSeconds给当前LocalDateTime添加或减去指定的秒数
IsAfter, isBefore检查此LocalDateTime是否在指定的日期时间之后或之前
withDayOfMonth返回此LocalDateTime的拷贝,并将月份中的某天设置为指定值
withMonth, withYear返回此LocalDateTime的拷贝,其月或年设置为指定值
withHour, withMinute, withSecond返回此LocalDateTime的拷贝,其小时/分钟/秒设置为指定值

LocalDateTime提供了各种静态方法来创建日期时间。 该方法现在带有三个重载方法返回当前的日期时间。 无参的方法是最容易使用的:

LocalDateTime now = LocalDateTime.now();

 

要创建具有特定日期和时间的LocalDateTime,请使用of方法。 此方法有多个重载,并允许传递日期时间或LocalDateLocalTime的单个部分。 以下是一些方法的签名。

public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute)
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute)
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute)
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute)
public static LocalDateTime of(LocalDate date, LocalTime time)

 

例如,下面的代码段创建一个LocalDateTime,代表2015年12月31日早上八点。

LocalDateTime endOfYear = LocalDateTime.of(2015, 12, 31, 8, 0);

 

可以使用plusXXXminusXXX方法创建LocalDateTime的拷贝。 例如,此代码创建一个LocalDateTime,它表示明天的同一时间。

LocalDateTime now = LocalDateTime.now();
LocalDateTime sameTimeTomorrow = now.plusHours(24);


 


Time Zones

互联网数字分配机构(IANA)维护一个可从此网页下载的时区数据库:

[http://www.iana.org/time-zones](http://www.iana.org/time-zones)

 

但为了便于查看,可以访问此Wikipedia页面:

http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Java日期和时间API也适用于时区。 抽象类ZoneId(在java.time包中)表示一个区域标识符。 它有一个名为getAvailableZoneIds的静态方法,它返回所有区域标识符。 下面展示了如何使用这种方法打印所有时区的排序列表。

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class TimeZoneDemo1 {
public static void main(String[] args) {
Set allZOneIds= ZoneId.getAvailableZoneIds();
List zOneList= new ArrayList<>(allZoneIds);
Collections.sort(zoneList);
for (String zoneId : zoneList) {
System.out.println(zoneId);
}
// alternatively, you can use this line of code to
// print a sorted list of zone ids
// ZoneId.getAvailableZoneIds().stream().sorted().
// forEach(System.out::println);
}
}

 

getAvailableZoneIds返回字符串的Set集合。 可以使用Collections.sort()或更优雅地通过调用它的stream方法对Set进行排序。 可以编写此代码对区域标识符进行排序。

ZoneId.getAvailableZoneIds().stream().sorted().forEach(System.out::println);

 

getAvailableZoneIds返回586个区域标识符的Set集合。 以下是上述代码中的一部分区域标识符。

Africa/Cairo
Africa/Johannesburg
America/Chicago
America/Los_Angeles
America/Mexico_City
America/New_York
America/Toronto
Antarctica/South_Pole
Asia/Hong_Kong
Asia/Shanghai
Asia/Tokyo
Australia/Melbourne
Australia/Sydney
Canada/Atlantic
Europe/Amsterdam
Europe/London
Europe/Paris
US/Central
US/Eastern
US/Pacific


 


ZonedDateTime

ZonedDateTime类以一个时区为日期时间的构建。例如,以下是一个时区的日期时间:

2015-12-31T10:59:59+01:00 Europe/Paris

 

ZonedDateTime始终是不可变的,时间分量的存储精度为纳秒。

ZonedDateTIme中一些重要方法的使用与LocalDateTime类似,只是多了一个时区的概念。可自行查阅API。

LocalDateTime一样,ZonedDateTime类现在提供静态nowof方法,并构造一个ZonedDateTime实例。 now方法创建一个ZonedDateTime代表执行的日期和时间。 无参now方法会使用计算机的默认时区创建ZonedDateTime

ZonedDateTime now = ZonedDateTime.now();

 

now的另一个重载方法允许传递区域标识符:

ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));

 

of方法也有好几个重载的方法。在所有情况下,都需要传递区域标识符。 第一个重载方法允许传递时区日期时间的每个部分,从年份到纳秒。

public static ZonedDateTime of(int year, int month, int dayOfMonth,
int hour, int minute, int second, int nanosecond,
ZoneId zone)

 

of方法的第二个重载方法需要LocalDateLocalTimeZoneId参数:

public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone)

 

of方法的最后一个重载方法需要LocalDateTimeZoneId参数。

public static ZonedDateTime of(LocalDateTime datetime, ZoneId zone)

LocalDateLocalDateTime一样,ZonedDateTime提供了使用plusXXXminusXXXwithXXX方法创建实例拷贝的方法。

例如,下面代码行创建一个带默认时区的ZonedDateTime,并调用它的minusDays方法以在三天前创建相同的ZonedDateTime



 


Duration

Duration类是基于时间的持续时间的构建。 它与Period类似,不同之处在于Duration的时间分量为纳秒精度,并考虑了ZonedDateTime实例之间的时区。 下表显示了Duration中重要的方法。
















































方法描述
between在两个时差的对象之间创建一个Duration实例,例如在两个LocalDateTime或两个ZonedDateTime之间。
ofYears, ofMonths, ofWeeks, ofDays, ofHours, ofMinutes, ofSeconds, ofNano创建给定年数/月/周/天/小时/分钟/秒/纳秒的Duration实例
of根据指定数量的时间单位创建Duration实例
toDays, toHours, toMinutes以int形式返回此Duration的天数/小时/分钟数
isNegative如果此Duration为负,则返回true。 否则返回false。
isZero如果此Duration长度为零,则返回true。 否则,返回false
plusDays, minusDays在此Duration内添加或减去指定的天数。
plusMonths, minusMonths在此Duration内添加或减去指定的月数。
plusYears, minusYears在Duration内添加或减去指定的年数
withSeconds以指定的秒数返回此Duration的拷贝。

可以通过调用静态方法betweenof来创建Duration。 下面的代码会在2015年1月26日11:10至2015年1月26日12:40之间创建两个LocalDateTimeDuration

import java.time.Duration;
import java.time.LocalDateTime;
public class DurationDemo1 {
public static void main(String[] args) {
LocalDateTime dateTimeA = LocalDateTime
.of(2015, 1, 26, 8, 10, 0, 0);
LocalDateTime dateTimeB = LocalDateTime
.of(2015, 1, 26, 11, 40, 0, 0);
Duration duration = Duration.between(
dateTimeA, dateTimeB);
System.out.printf("There are %d hours and %d minutes.%n",
duration.toHours(),
duration.toMinutes() % 60);
}
}

 

运行DurationDemo1类的结果是这样的。

There are 3 hours and 30 minutes.

 

下面的代码在两个ZoneDateTime之间创建一个Duration,具有相同的日期和时间,但时区不同。

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class DurationDemo2 {
public static void main(String[] args) {
ZonedDateTime zdt1 = ZonedDateTime.of(
LocalDateTime.of(2015, Month.JANUARY, 1,
8, 0),
ZoneId.of("America/Denver"));
ZonedDateTime zdt2 = ZonedDateTime.of(
LocalDateTime.of(2015, Month.JANUARY, 1,
8, 0),
ZoneId.of("America/Toronto"));
Duration duration = Duration.between(zdt1, zdt2);
System.out.printf("There are %d hours and %d minutes.%n",
duration.toHours(),
duration.toMinutes() % 60);
}
}

 

运行DurationDemo2类在控制台上打印如下结果。

There are -2 hours and 0 minutes.

 

这是预料之中的,因为时区America/DenverAmerica/Toronto之间有两个小时的差异。

作为一个更复杂的例子,下面的代码显示了一个公交车旅行时间计算器。 它有一个方法calculateTravelTime,它需要一个离开的ZonedDateTime实例和一个到达的ZonedDateTime实例。 该代码调用calculateTravelTime方法两次。 这两次公交车都在丹佛早上8点从科罗拉多州丹佛出发,并于多伦多时间第二天早上8点抵达多伦多。 公交车首次于2014年3月8日启程,第二次于2014年3月18日启程。

两种情况下的旅行时间是多少?


import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TravelTimeCalculator {
public Duration calculateTravelTime(
ZonedDateTime departure, ZonedDateTime arrival) {
return Duration.between(departure, arrival);
}
public static void main(String[] args) {
TravelTimeCalculator calculator =
new TravelTimeCalculator();
ZonedDateTime departure1 = ZonedDateTime.of(
LocalDateTime.of(2014, Month.MARCH, 8,
8, 0),
ZoneId.of("America/Denver"));
ZonedDateTime arrival1 = ZonedDateTime.of(
LocalDateTime.of(2014, Month.MARCH, 9,
8, 0),
ZoneId.of("America/Toronto"));
Duration travelTime1 = calculator
.calculateTravelTime(departure1, arrival1);
System.out.println("Travel time 1: "
+ travelTime1.toHours() + " hours");
ZonedDateTime departure2 = ZonedDateTime.of(
LocalDateTime.of(2014, Month.MARCH, 18,
8, 0),
ZoneId.of("America/Denver"));
ZonedDateTime arrival2 = ZonedDateTime.of(
LocalDateTime.of(2014, Month.MARCH, 19,
8, 0),
ZoneId.of("America/Toronto"));
Duration travelTime2 = calculator
.calculateTravelTime(departure2, arrival2);
System.out.println("Travel time 2: "
+ travelTime2.toHours() + " hours");
}
}

运行结果为:

Travel time 1: 21 hours
Travel time 2: 22 hours

为什么有这个区别? 因为2014年的夏令时从3月9日星期日凌晨2点开始。 因此,在2014年3月8日至2014年3月9日之间“失去”了一小时。



 


Formatting A Date-Time

可以使用java.time.format.DateTimeFormatter格式化本地或时区日期时间。LocalDateLocalDateTimeLocalTimeZoneDateTime类提供具有以下签名的格式方法。

public java.lang.String format(java.time.format.DateTimeFormatter formatter)

很明显,要格式化日期或时间,必须首先创建DateTimeFormatter实例。

 

下面的代码使用两个格式化实例格式化当前日期。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class DateTimeFormatterDemo1 {
public static void main(String[] args) {
DateTimeFormatter formatter1 = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM);
LocalDateTime example = LocalDateTime.of(
2000, 3, 19, 10, 56, 59);
System.out.println("Format 1: " + example
.format(formatter1));
DateTimeFormatter formatter2 = DateTimeFormatter
.ofPattern("MMMM dd, yyyy HH:mm:ss");
System.out.println("Format 2: " +
example.format(formatter2));
}
}

运行结果如下:(第一个结果取决于你的区域设置)。

Format 1: 19-Mar-2000 10:56:59 AM
Format 2: March 19, 2000 10:56:59


 


Parsing A Date-Time


在Java Date和Time API的许多类中有两种parse方法。第一个需要格式化实例,第二个则不需要。后一个方法会根据默认模式解析日期时间。要使用自己的格式化模式,请使用DateTimeFormatter。如果传递的字符串不能被解析,那么解析方法将抛出一个DateTimeParseException

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;
public class AgeCalculator {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");
public Period calculateAge(LocalDate birthday) {
LocalDate today = LocalDate.now();
return Period.between(birthday, today);
}
public LocalDate getBirthday() {
Scanner scanner = new Scanner(System.in);
LocalDate birthday;
while (true) {
System.out.println("Please enter your birthday "
+ "in yyyy-MM-dd format (e.g. 1980-9-28): ");
String input = scanner.nextLine();
try {
birthday = LocalDate.parse(input, formatter);
return birthday;
} catch(DateTimeParseException e) {
System.out.println("Error! Please try again");
}
}
}
public static void main(String[] args) {
AgeCalculator ageCalculator = new AgeCalculator();
LocalDate birthday = ageCalculator.getBirthday();
Period age = ageCalculator.calculateAge(birthday);
System.out.printf("Today you are %d years, %d months"
+ " and %d days old%n",
age.getYears(), age.getMonths(), age.getDays());
}
}

 

AgeCalculator类有两个方法,getBirthdaycalculateAgegetBirthday方法使用Scanner类来读取用户输入,并使用DateTimeFormatter类将输入解析到LocalDate中。 getBirthday方法一直请求一个日期,直到用户输入正确格式的日期,在这种情况下,方法返回。 calculateAge方法需要一个生日,并在生日和今天的日期之间创建一个Period实例。

如果运行这个例子,会在控制台上看到这个。

Please enter your birthday in yyyy-MM-dd format (e.g. 1980-9-28):

如果以正确的格式输入日期,则程序将打印计算的年龄,如下所示。

Today you are 79 years, 0 months and 15 days old


 


总结



  • java.time包中,Instant类表示时间线上的一个点,通常用于对时间进行操作。 LocalDate类为没有时间和时区部分的日期建模,例如,用于表示生日。



  • 如果你需要日期和时间,那么LocalDateTime就是为你准备的。 例如,订单发货日期可能需要一个日期以外的时间来使订单更容易跟踪。 如果你需要一段时间但不关心日期,那么可以使用LocalTime



  • 如果时区很重要,日期和时间API提供ZonedDateTime类。 顾名思义,这个类表示带有时区日期时间。 例如,你可以使用此类来计算位于不同时区的两个机场之间的飞行时间。



  • 然后有两个类来测量时间总计,即Duration类和Period类。 这两个类是相似的,除了Duration是基于时间,但而Period是基于日期的Duration提供了纳秒精度的时间量。 例如,可以模拟飞行时间,因为它通常以小时数和分钟数表示。 另一方面,如果只关心天数,月数或年数,例如计算一个人的年龄,则Period更为适用。



  • java.time包也带有两个枚举DayOfWeekMonthDayOfWeek表示从一周的一天,从周一开始到周日。 Month枚举代表这一年的十二个月,从1月到12月。



  • 处理日期和时间通常涉及解析和格式。 日期和时间API通过在所有主要类中提供parseformat方法来解决这两个问题。 另外,java.time.format包含一个用于格式化日期和时间的DateTimeFormatter类。



(本文摘自:码匠安徒生)




推荐阅读
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 在优化Nginx与PHP的高效配置过程中,许多教程提供的配置方法存在诸多问题或不良实践。本文将深入探讨这些常见错误,并详细介绍如何正确配置Nginx和PHP,以实现更高的性能和稳定性。我们将从Nginx配置文件的基本指令入手,逐步解析每个关键参数的最优设置,帮助读者理解其背后的原理和实际应用效果。 ... [详细]
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • DVWA学习笔记系列:深入理解CSRF攻击机制
    DVWA学习笔记系列:深入理解CSRF攻击机制 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • Python多线程编程技巧与实战应用详解 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
author-avatar
陨落星辰W_955
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有