java8中时间的使用方法

发布时间:2020-10-19 16:07:34 作者:小新
来源:亿速云 阅读:97

这篇文章给大家分享的是有关java8中时间的使用方法的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。

为什么需要新的时间API?

在Java 8之前的日期/时间API之前,现有的与日期和时间相关的类存在诸多问题,其中主要有:

  1. Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义

  2. java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

  3. 对于时间、时间戳、格式化以及解析,并没有一些明确定义的类。对于格式化和解析的需求,我们有java.text.DateFormat抽象类,但通常情况下,SimpleDateFormat类被用于此类需求。

  4. 所有的日期类都是可变的,因此他们都不是线程安全的,这是Java日期类最大的问题之一。

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

  6. 在现有的日期和日历类中定义的方法还存在一些其他的问题,但以上问题已经很清晰地表明:Java需要一个健壮的日期/时间类。这也是为什么Joda Time在Java日期/时间需求中扮演了高质量替换的重要角色。

  7. 使用java8之前的日期注意

   使用Calendar类实现日期和时间字段之间转换
   使用DateFormat类来格式化和分析日期字符串
   而Date只用来承载日期和时间信息

java8 概念

瞬时时间(Instant),持续时间(duration),日期(date),时间(time),时区(time-zone)以及时间段(Period)。Java 8仍然延用了ISO的日历体系,并且与它的前辈们不同,java.time包中的类是不可变且线程安全的。新的时间及日期API位于java.time包中,下面是里面的一些关键的类:

java8时间API特性

java8日期/时间API包

java8 API介绍和使用

LocalDate

LocalDate 依然是一个不可变类,它关注时间中年月日部分

初始化实例
public static LocalDate now():截断当前系统时间的年月日信息并初始化一个实例对象
public static LocalDate of(int year, int month, int dayOfMonth):显式指定年月日信息
public static LocalDate ofYearDay(int year, int dayOfYear):根据 dayOfYear 可以推出 month 和 dayOfMonth
public static LocalDate ofEpochDay(long epochDay):相对于格林零时区时间的日偏移量
…………

示例

// 取当前日期:
LocalDate today = LocalDate.now(); // -> 2019-01-31
// 根据年月日取日期,12月就是12:
LocalDate crischristmas = LocalDate.of(2018, 12, 25); // -> 2018-12-25
// 根据字符串取:
LocalDate endOfFeb = LocalDate.parse("2018-12-25"); // 严格按照ISO yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式

// 如何获取1周后的日期
LocalDate oneToday = today.plus(1, ChronoUnit.WEEKS); // ->2019-02-07
//一年前的日期
LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2019-01-01
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2019-01-02
// 取本月最后一天,再也不用计算是28,29,30还是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2019-01-31
// 取下一天:
LocalDate firstDay = lastDayOfThisMonth.plusDays(1); // 变成了2019-02-01
// 取2019年1月第一个周一
LocalDate firstMonday = LocalDate.parse("2019-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2019-01-07

在java8中,可以使用MonthDay,该类不包含年份信息,当然还有一个类是YearMonth

LocalDate birthday = LocalDate.of(1990, 10, 12);
MonthDay birthdayMd = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
MonthDay today = MonthDay.from(LocalDate.of(2019, 10, 12)); 
System.out.println(today.equals(birthdayMd));
//结果
true
TemporalAdjuster

但是有些时候我们要面临更复杂的时间操作,比如将时间调到下一个工作日,或者是下个月的最后一天,这时候我们可以使用with()方法的另一个重载方法,它接收一个TemporalAdjuster参数,可以使我们更加灵活的调整日期:

LocalDate date7 = date.with(nextOrSame(DayOfWeek.SUNDAY));      // 返回下一个距离当前时间最近的星期日
LocalDate date9 = date.with(lastInMonth(DayOfWeek.SATURDAY));   // 返回本月最后一个星期六

如果本身API不满足你的需求,你还可以创建自定义的TemporalAdjuster接口的实现

LocalTime

类似于 LocalDate,LocalTime 专注于时间的处理,它提供小时,分钟,秒,毫微秒的各种处理

初始化LocalTime实例
public static LocalTime now():根据系统当前时刻获取其中的时间部分内容
public static LocalTime of(int hour, int minute):显式传入小时和分钟来构建一个实例对象
public static LocalTime of(int hour, int minute, int second):通过传入时分秒构造实例
public static LocalTime of(int hour, int minute, int second, int nanoOfSecond):传入时分秒和毫微秒构建一个实例
public static LocalTime ofSecondOfDay(long secondOfDay):传入一个长整型数值代表当前日已经过去的秒数
public static LocalTime ofNanoOfDay(long nanoOfDay):传入一个长整型代表当前日已经过去的毫微秒数

示例

//包含毫秒
LocalTime now = LocalTime.now(); // 11:09:09.240
//不包含毫秒  
LocalTime now = LocalTime.now().withNano(0)); // 11:09:09
//构造时间  
LocalTime zero = LocalTime.of(0, 0, 0); // 00:00:00
LocalTime mid = LocalTime.parse("12:00:00"); // 12:00:00
LocalTime twoHour = now.plusHours(2);

LocalDateTime

LocalDateTime类是LocalDate和LocalTime的结合体,可以通过of()方法直接创建,也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime

LocalDateTime ldt1 = LocalDateTime.of(2017, Month.JANUARY, 4, 17, 23, 52);

LocalDate localDate = LocalDate.of(2017, Month.JANUARY, 4);
LocalTime localTime = LocalTime.of(17, 23, 52);
LocalDateTime ldt2 = localDate.atTime(localTime);

LocalDateTime也提供用于向LocalDate和LocalTime的转化:

LocalDate date = ldt1.toLocalDate();
LocalTime time = ldt1.toLocalTime();

Instant

Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似,不过Instant可以精确到纳秒(Nano-Second),System.currentTimeMillis()方法只精确到毫秒(Milli-Second)。如果查看Instant源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)。Instant除了使用now()方法创建外,还可以通过ofEpochSecond方法创建:

Instant instant = Instant.ofEpochSecond(120, 100000);

时间差

关于时间差的计算,主要涉及到两个类,年月日的日期间差值的计算使用 Period 类足以,而时分秒毫秒的时间的差值计算则需要使用Duration类。

 LocalDate date = LocalDate.of(2019,01,22);
    LocalDate date1 = LocalDate.now();
    Period period = Period.between(date,date1);
    System.out.println(period.getYears() + "年" +
            period.getMonths() + "月" +
            period.getDays() + "天");

    LocalTime time = LocalTime.of(20,30);
    LocalTime time1 = LocalTime.of(23,59);
    Duration duration = Duration.between(time,time1);
    System.out.println(duration.toMinutes() + "分钟");

ZonedDateTime

无论是我们的 LocalDate,或是 LocalTime,甚至是 LocalDateTime,它们基本是时区无关的,内部并没有存储时区属性,而基本用的系统默认时区。往往有些场景之下,缺乏一定的灵活性。

ZonedDateTime 可以被理解为 LocalDateTime 的外层封装,它的内部存储了一个 LocalDateTime 的实例,专门用于普通的日期时间处理。此外,它还定义了 ZoneId 和 ZoneOffset 来描述时区的概念。

ZonedDateTime 和 LocalDateTime 的一个很大的不同点在于,后者内部并没有存储时区,所以对于系统的依赖性很强,往往换一个时区可能就会导致程序中的日期时间不一致。
而后者则可以通过传入时区的名称,使用 ZoneId 进行匹配存储,也可以通过传入与零时区的偏移量,使用 ZoneOffset 存储时区信息。

初始化实例
public static ZonedDateTime now():系统将以默认时区计算并存储日期时间信息
public static ZonedDateTime now(ZoneId zone):指定时区
public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone):指定日期时间和时区
public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone)
public static ZonedDateTime ofInstant(Instant instant, ZoneId zone):通过时刻和时区构建实例对象
等等

示例

 ZonedDateTime zonedDateTime = ZonedDateTime.now();
    System.out.println(zonedDateTime); 
    //->2019-01-31T16:27:23.179+08:00[Asia/Shanghai]

    LocalDateTime localDateTime = LocalDateTime.now();
    ZoneId zoneId = ZoneId.of("America/Los_Angeles");
    ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime,zoneId);
    System.out.println(zonedDateTime1);
    // ->2019-01-31T16:27:23.179-08:00[America/Los_Angeles]


    Instant instant = Instant.now();
    ZoneId zoneId1 = ZoneId.of("GMT");
    ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,zoneId1);
    System.out.println(zonedDateTime2);
    // ->2019-01-31T08:27:23.183Z[GMT]

格式化日期时间

Java 8 的新式日期时间 API 中,DateTimeFormatter 作为格式化日期时间的主要类,它与之前的 DateFormat 类最大的不同就在于它是线程安全的,如果需要的话,可以赋值给一个静态变量。

DateTimeFormatter类提供了许多预定义的格式器,你也可以自定义自己想要的格式。当然根据约定,它还有一个parse()方法是用于将字符串转换成日期的,如果转换期间出现任何错误,它会抛出DateTimeParseException异常。类似的,DateFormatter类也有一个用于格式化日期的format()方法,它出错的话则会抛出DateTimeException异常

再说一句,“MMM d yyyy”与“MMm dd yyyy”这两个日期格式也略有不同,前者能识别出"Jan 2 2018"与"Jan 14 2018"这两个串,而后者如果传进来的是"Jan 2 2018"则会报错,因为它期望月份处传进来的是两个字符。为了解决这个问题,在天为个位数的情况下,你得在前面补0,比如"Jan 2 2018"应该改为"Jan 02 2018"。

public static void main(String[] a){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println(formatter.format(localDateTime));

    String str = "2008年08月23日 23:59:59";
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime localDateTime2 = LocalDateTime.parse(str,formatter2);
    System.out.println(localDateTime2);

}

java8 时间与老版本时间转换

因为java8之前Date是包含日期和时间的,而LocalDate只包含日期,LocalTime只包含时间,所以与Date在互转中,势必会丢失日期或者时间,或者会使用起始时间。如果转LocalDateTime,那么就不存在信息误差。

/Date与Instant的相互转化
Instant instant  = Instant.now();
Date date = Date.from(instant);
Instant instant2 = date.toInstant();
        
//Date转为LocalDateTime
Date date2 = new Date();
LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date2.toInstant(), ZoneId.systemDefault());
        
//LocalDateTime转Date
LocalDateTime localDateTime3 = LocalDateTime.now();
Instant instant3 = localDateTime3.atZone(ZoneId.systemDefault()).toInstant();
Date date3 = Date.from(instant);

//LocalDate转Date
//因为LocalDate不包含时间,所以转Date时,会默认转为当天的起始时间,00:00:00
LocalDate localDate4 = LocalDate.now();
Instant instant4 = localDate4.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date date4 = Date.from(instant);


// Calendar to Instant
Instant time = Calendar.getInstance().toInstant();
System.out.println(time);

// TimeZone to ZoneId
ZoneId defaultZone = TimeZone.getDefault().toZoneId();
System.out.println(defaultZone);
 
// ZonedDateTime from specific Calendar
ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();
System.out.println(gregorianCalendarDateTime);
 
 
GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);
System.out.println(gc);

感谢各位的阅读!关于java8中时间的使用方法就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到吧!

推荐阅读:
  1. java8中处理日期和时间
  2. Java8中CompletableFuture的使用方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java8 中时 ava

上一篇:软件怎样安装在虚拟主机上

下一篇:怎样注册免费的虚拟主机空间

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》