时间类框架

Posted by 麦子 on Thursday, 2019年12月26日

[TOC]

时间结构图

jdk1.8比以前的时间操作类比较,所有类都是不可变的、线程安全的

java.time  包含值对象的基础包
java.time.chrono  提供对不同的日历系统的访问
java.time.format  格式化和解析时间和日期
java.time.temporal  包括底层框架和扩展特性
java.time.zone  包含时区支持的类

java.time包

377964-20190928151623416-1124322506

常用类介绍

转载:https://www.jianshu.com/p/19bd58b30660

**LocalDateTime:**只存储了日期和时间,如:2017-03-21T14:02:43.455。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值设为0)

**LocalDate:**只存储了日期,如:2017-03-21。

**LocalTime:**只存储了时间,如:14:02:43.455。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值设为0)

**ZonedDateTime:**包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。

**Year:**只表示年份。

**Month:**只表示月份。

**YearMonth:**只表示年月。

**MonthDay:**只表示月日。

**DayOfWeek:**只存储星期的一天。

Clock: 它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。

Instant: 时间戳,与System.currentTimeMillis()类似。

ZonedDateTime: 可以得到特定时区的日期/时间

Duration: 是用来计算两个日期的时间差,表示一个时间段。

**Period:**用来表示以年月日来衡量一个时间段。

方法前缀的含义,统一了api

   of 静态工厂方法(用类名去调用)
parse 静态工厂方法关注于解析(用类名去调用)
  now 静态工厂方法用当前时间创建实例(用类名去调用)
  get 获取某些东西的值
   is 检查某些东西的是否是true
 with 返回一个部分状态改变了的时间日期对象拷贝(单独一个with方法,参数为TemporalAdjusters类型)
 plus 返回一个时间增加了的时间日期对象拷贝(如果参数是负数也能够有minus方法的效果)
minus 返回一个时间减少了的时间日期对象拷贝
   to 把当前时间日期对象转换成另外一个可能会损失部分状态.
   at 把这个对象与另一个对象组合起来例如 date.atTime(time)
 format :根据某一个DateTimeFormatter格式化为字符串

新时间API类都实现了一系列方法用以完成通用的任务,如:加、减、格式化、解析、从日期/时间中提取单独部分,等等

time包里面的类实例如果用了上面的方法而被修改了,那么会返回一个新的实例过来,而不像Calendar那样可以在同一个实例进行不同的修改,体现了不可变

常用方法

转载地址:https://juejin.im/post/5da3fd81f265da5b81794e71

LocalDate-如何获得日期

 // 只获取日期
LocalDate today = LocalDate.now();
System.out.println(today);

int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();

System.out.printf("Year : %d Month : %d day : %d \t %n", year, month, day);

运行结果
2019-12-26
Year : 2019 Month : 12 day : 26  
  
// 只获取日期
LocalDate today = LocalDate.now();
// 月份中的第几天
int dayOfMonth = today.getDayOfMonth();
// 一周的第几天
DayOfWeek dayOfWeek = today.getDayOfWeek();
// 月份的天数
int length = today.lengthOfMonth();
// 是否为闰年
boolean leapYear = today.isLeapYear();

System.out.println(today+" "+dayOfMonth+" "+" "+dayOfWeek+" "+length+" "+leapYear);  

运行结果
2019-12-26 26  THURSDAY 31 false  

上面通过now获取LocalDate对象,也可以通过静态方法of()或parse创建任意一个日期。再也不用像之前一样年只能从1900年开始,月必须从0开始等。

LocalDate oneDay = LocalDate.of(2019,10,1);
System.out.println(oneDay);

LocalDate parseDay = LocalDate.parse("2019-10-01");
System.out.println(parseDay);

运行结果
2019-10-01

LocalDate重写了equals方法,让日期的比较也变得简单了。

// 定义任意日期
LocalDate oneDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay);

// 定义任意比较
LocalDate anyDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay.equals(anyDay));

运行结果
2019-10-01
true

同时,针对日期还可延伸出MonthDay或YearMonth类,顾名思义,只包含月天或年月。同样适用于equals方法来比较。

另外使用before和after可以比较两个日期前后时间。

boolean notBefore = LocalDate.parse("2019-10-01").isBefore(LocalDate.parse("2019-10-02"));
boolean isAfter = LocalDate.parse("2019-10-01").isAfter(LocalDate.parse("2019-10-02"));

对日期进行前一天后一天或前一个月的加减也变得十分方便。

LocalDate tomorrowDay = LocalDate.now().plusDays(1);
LocalDate nextMonth =  LocalDate.now().plusMonths(1);

还有,我们在实战的时候往往要获取某一天的开始时间和当天所在月的第一天等。

LocalDate.now().atStartOfDay();
LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());

LocalTime-如何获取时间

LocalTime和LocalDate类似,区别在于LocalDate不包含具体时间,而LocalTime包含具体时间。同样可以使用now或of方法来获得对象。

LocalTime localTime = LocalTime.now();

LocalTime oneTime = LocalTime.of(10,10,10);

LocalDate类似它也拥有parse、isBefore、获取时间单元等方法,就不再赘述。

需要注意的是,LocalTime获得的时间格式为:11:41:58.904。也就是,HH:mm:ss.nnn,这里nnn是纳秒。

还有一个在实战中查询日期区间时我们经常定义的“23:59:59.99”常量再也不用自己定义了。

// 23:59:59.999999999
LocalTime maxTime = LocalTime.MAX;
// 00:00
LocalTime minTime = LocalTime.MIN;

LocalDateTime-日期和时间的组合

LocalDateTime表示日期和时间组合。可以通过of()方法直接创建,也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime。

LocalDateTime now = LocalDateTime.now();

LocalDateTime oneTime = LocalDateTime.of(2019,10,14,10,12,12);

// 拼接日期
LocalTime.now().atDate(LocalDate.now());

LocalDateTime与LocalDate和LocalTime之间可以相互转化。其他日期增减等操作与上面的类似。

Instant-获取时间戳

Instant用于一个时间戳,与System.currentTimeMillis()类似,但Instant可以精确到纳秒(Nano-Second)。

Instant除了可以使用now()方法创建,还可以通过ofEpochSecond方法创建。

Instant now = Instant.now();

Instant.ofEpochSecond(365 * 24 * 60, 100);

其中ofEpochSecond第一个参数表示秒,第二个参数表示纳秒。整体表示:从1970-01-01 00:00:00开始后的365天100纳秒的时间点。

Duration-获取时间段

Duration的内部实现与Instant类似,但Duration表示时间段,通过between方法创建。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);

// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

Duration对象还可以通过of()方法创建,该方法参数为时间段长度和时间单位。

// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);

Period-获取日期段

Period与Duration类似,获取一个时间段,只不过单位为年月日,也可以通过of方法和between方法创建,between方法接收的参数为LocalDate。

Period period = Period.of(1, 10, 25);

Period period1 = Period.between(LocalDate.now(), LocalDate.now().plusYears(1));

ZonedDateTime-创建时区时间

ZonedDateTime类,用于处理带时区的日期和时间。ZoneId表示不同的时区。大约有40不同的时区。

获取所有时区集合:

Set allZoneIds = ZoneId.getAvailableZoneIds();

创建时区:

ZoneId zoneId = ZoneId.of("Asia/Shanghai");

把LocalDateTime转换成特定的时区:

ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), zoneId);

另外和时区一起使用的类是OffsetDateTime类,OffsetDateTime是不变的,表示date-time偏移,存储所有日期和时间字段,精确至纳秒,从UTC/Greenwich计算偏移。

时间日期格式化

Java8对日期的格式化操作非常简单,首先看到上面的类大多都提供了parse方法,可以直接通过解析字符串得到对应的对象。

而日期和时间的格式化可通过LocalDateTime的format方法进行格式化。

/***************时间转字符串*************************/ 
LocalDateTime dateTime = LocalDateTime.now();
String str = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println(str);

str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(str);



/***************字符串转时间格式*************************/ 
String str1 = "2014==04==12 01时06分09秒";
// 根据需要解析的日期、时间字符串定义解析所用的格式器
DateTimeFormatter fomatter1 = DateTimeFormatter.ofPattern("yyyy==MM==dd HH时mm分ss秒");
// 执行解析
LocalDateTime dt1 = LocalDateTime.parse(str1, fomatter1);
System.out.println(dt1); // 输出 2014-04-12T01:06:09

String time = "2019-12-26 17:48:22";
DateTimeFormatter fomatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime timeDate = LocalDateTime.parse(time, fomatter2);
System.out.println(timeDate);

Clock

Clock 它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。

TimeUnit

转载地址:https://www.jianshu.com/p/4ab62e4a328f

TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段。

常用的颗粒度

TimeUnit.DAYS          //天
TimeUnit.HOURS         //小时
TimeUnit.MINUTES       //分钟
TimeUnit.SECONDS       //秒
TimeUnit.MILLISECONDS  //毫秒

颗粒度转换

public long toMillis(long d)    //转化成毫秒
public long toSeconds(long d)  //转化成秒
public long toMinutes(long d)  //转化成分钟
public long toHours(long d)    //转化成小时
public long toDays(long d)     //转化天
import java.util.concurrent.TimeUnit;

public class TimeUnitTest {

    public static void main(String[] args) {
        // 默认转换只能和上一级进行转换。    
        
        //convert 1 day to 24 hour
        System.out.println(TimeUnit.DAYS.toHours(1));
        //convert 1 hour to 60*60 second.
        System.out.println(TimeUnit.HOURS.toSeconds(1));
    }

}

自己带上单位转换

//convert 3 days to 72 hours.
System.out.println(TimeUnit.HOURS.convert(3, TimeUnit.DAYS));

延时,可替代Thread.sleep()

import java.util.concurrent.TimeUnit;

public class ThreadSleep {

    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            private int count = 0;

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        // Thread.sleep(500); //sleep 单位是毫秒
                        TimeUnit.SECONDS.sleep(1); // 单位可以自定义,more convinent
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                    System.out.println(count);
                }
            }
        });
        t.start();
    }
}

20个常用使用示例

转载地址:https://blog.csdn.net/chenleixing/article/details/44408875

获取当天的日期

LocalDate today = LocalDate.now(); System.out.println("Today's Local date : " + today); 
 
Output 
Today's Local date : 2014-01-14

获取当前的年月日

LocalDate today = LocalDate.now(); 
int year = today.getYear(); 
int month = today.getMonthValue(); 
int day = today.getDayOfMonth(); 
System.out.printf("Year : %d Month : %d day : %d \t %n", year, month, day); 
 
Output 
Today's Local date : 2014-01-14 
Year : 2014 Month : 1 day : 14

获取某个特定的日期

LocalDate dateOfBirth = LocalDate.of(2010, 01, 14); 
System.out.println("Your Date of birth is : " + dateOfBirth); 

Output : Your Date of birth is : 2010-01-14

检查两个日期是否相等

LocalDate date1 = LocalDate.of(2014, 01, 14); 
if(date1.equals(today)){ 
    System.out.printf("Today %s and date1 %s are same date %n", today, date1); 
} 
 
Output 
today 2014-01-14 and date1 2014-01-14 are same date  

检查重复事件,比如说生日

LocalDate dateOfBirth = LocalDate.of(2010, 01, 14); 
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth()); 
MonthDay currentMonthDay = MonthDay.from(today); 
if(currentMonthDay.equals(birthday)){ 
    System.out.println("Many Many happy returns of the day !!"); 
}else{ 
    System.out.println("Sorry, today is not your birthday"); 
} 
 
Output: Many Many happy returns of the day !!

获取当前时间

LocalTime time = LocalTime.now(); System.out.println("local time now : " + time);
 
Output 
local time now : 16:33:33.369 // in hour, minutes, seconds, nano seconds

如何增加时间里面的小时数

LocalTime time = LocalTime.now(); 
LocalTime newTime = time.plusHours(2); // adding two hours 
System.out.println("Time after 2 hours : " + newTime); 
 
Output : 
Time after 2 hours : 18:33:33.369

如何获取1周后的日期

LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); 
System.out.println("Today is : " + today); 
System.out.println("Date after 1 week : " + nextWeek); 
 
Output: 
Today is : 2014-01-14 
Date after 1 week : 2014-01-21

一年前后的日期

LocalDate previousYear = today.minus(1, ChronoUnit.YEARS); 
System.out.println("Date before 1 year : " + previousYear); 
LocalDate nextYear = today.plus(1, YEARS); 
System.out.println("Date after 1 year : " + nextYear); 
 
Output: 
Date before 1 year : 2013-01-14 
Date after 1 year : 2015-01-14

如何判断某个日期是在另一个日期的前面还是后面

LocalDate tomorrow = LocalDate.of(2014, 1, 15); 
if(tommorow.isAfter(today)){ 
    System.out.println("Tomorrow comes after today"); 
}

LocalDate yesterday = today.minus(1, DAYS); 
if(yesterday.isBefore(today)){ 
    System.out.println("Yesterday is day before today"); 
} 
 
Output: 
Tomorrow comes after today 
Yesterday is day before today

表示固定的日期,比如信用卡过期时间

YearMonth currentYearMonth = YearMonth.now(); 
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth()); 

YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY); 
System.out.printf("Your credit card expires on %s %n", creditCardExpiry); 
 
Output: 
Days in month year 2014-01: 31 
Your credit card expires on 2018-02

检查闰年

if(today.isLeapYear()){ 
    System.out.println("This year is Leap year"); 
}else { 
    System.out.println("2014 is not a Leap year"); 
} 
 
Output: 2014 is not a Leap year

两个日期之间包含多少天,多少个月

LocalDate java8Release = LocalDate.of(2014, Month.MARCH, 14); 
Period periodToNextJavaRelease = 
Period.between(today, java8Release); 
System.out.println("Months left between today and Java 8 release : " + periodToNextJavaRelease.getMonths() ); 
 
Output: 
Months left between today and Java 8 release : 2

如何获取当前时间戳

Instant timestamp = Instant.now(); 
System.out.println("What is value of this instant " + timestamp); 
 
Output : 
What is value of this instant 2014-01-14T08:33:33.379Z

使用预定义的格式器来对日期进行解析/格式化

String dayAfterTommorrow = "20140116"; 
LocalDate formatted = LocalDate.parse(dayAfterTommorrow, 
DateTimeFormatter.BASIC_ISO_DATE); 
System.out.printf("Date generated from String %s is %s %n", dayAfterTommorrow, formatted); 
 
Output : 
Date generated from String 20140116 is 2014-01-16

使用自定义的格式器来解析日期

String goodFriday = "Apr 18 2014"; 
try { 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");     
    LocalDate holiday = LocalDate.parse(goodFriday, formatter); 
    System.out.printf("Successfully parsed String %s, date is %s%n", goodFriday, holiday); 
} catch (DateTimeParseException ex) { 
    System.out.printf("%s is not parsable!%n", goodFriday); 
    ex.printStackTrace(); 
} 
 
Output : 
Successfully parsed String Apr 18 2014, date is 2014-04-18

对日期进行格式化,转换成字符串

LocalDateTime arrivalDate = LocalDateTime.now(); 
try { 
    DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm a"); 
    String landing = arrivalDate.format(format); 
    System.out.printf("Arriving at : %s %n", landing); 
    } catch (DateTimeException ex) { 
    System.out.printf("%s can't be formatted!%n", arrivalDate); 
    ex.printStackTrace(); 
} 
 
Output : Arriving at : Jan 14 2014 04:33 PM


/***************时间转字符串*************************/ 
LocalDateTime dateTime = LocalDateTime.now();
String str = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println(str);

str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(str);



/***************字符串转时间格式*************************/ 
String str1 = "2014==04==12 01时06分09秒";
// 根据需要解析的日期、时间字符串定义解析所用的格式器
DateTimeFormatter fomatter1 = DateTimeFormatter.ofPattern("yyyy==MM==dd HH时mm分ss秒");
// 执行解析
LocalDateTime dt1 = LocalDateTime.parse(str1, fomatter1);
System.out.println(dt1); // 输出 2014-04-12T01:06:09

String time = "2019-12-26 17:48:22";
DateTimeFormatter fomatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime timeDate = LocalDateTime.parse(time, fomatter2);
System.out.println(timeDate);


「真诚赞赏,手留余香」

真诚赞赏,手留余香

使用微信扫描二维码完成支付