Java8 日期、时间骚操作

Java 专栏收录该内容
6 篇文章 0 订阅

在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题。故此,Java8引入了一套全新的日期时间处理API,新的API基于ISO标准日历系统。

常用的API类如下:

LocalDate       //只包含日期,比如:2018-09-24
LocalTime       //只包含时间,比如:10:32:10
LocalDateTime   //包含日期和时间,比如:2018-09-24 10:32:10
java.time.format.DateTimeFormatter      //时间格式化类
Instant         //时间戳
Peroid          //时间段
Duration        //持续时间、时间差
ZoneOffset      //时区偏移量,比如:+8:00
ZonedDateTime   //带时区的日期时间
Clock           //时钟,可用于获取当前时间戳

LocalDate和LocalTime

从类名就可以看出,LocalDate是表示年月日,而LocalTime是表示时分秒

LocalDate

LocalDate 一般使用场景如下:

LocalDate date = LocalDate.of(2019,6,20);
int year = date.getYear();  //2019
Month month = date.getMonth(); // NOVEMBER
int mon = date.getMonthValue();//6
int dayOfMonth = date.getDayOfMonth(); //20
DayOfWeek dayOfWeek = date.getDayOfWeek();  //SUNDAY
int i = date.lengthOfMonth();   //30
boolean leapYear = date.isLeapYear();  //false
//获取现在时间
LocalDate now = LocalDate.now();  //2019-06-20
boolean dateEqual =  now.equals(LocalDate.of(year,mon,dayOfMonth));//true

除了getxxx方法,还可以使用TemporalField参数给get方法获取相同的信息(ChronoField是TemporalField的实现)

//获取现在时间
LocalDate now = LocalDate.now();  //2019-06-20

int year = now.get(ChronoField.YEAR); //2019
int month = now.get(ChronoField.MONTH_OF_YEAR);//6
int dayOfMonth = now.get(ChronoField.DAY_OF_MONTH);//20
int dayOfWeek = now.get(ChronoField.DAY_OF_WEEK);//4

LocalTime

LocalTime now = LocalTime.now();//14:37:26.142
LocalTime time = LocalTime.of(18,18,18);//18:18:18.0
int hour = time.getHour();  //18
int minute = time.getMinute();  //18
int second = time.getSecond();  //18
int nano = time.getNano();  //0

LocalDateTime

LocalDateTime类,结合了上面两个类,可以同时表示年月日和时分秒

//LocalDateTime基本使用
LocalDateTime localDateTime = LocalDateTime.of(2019,6,20,18,18,18);
//创建LocalDate对象
LocalDate localDate = LocalDate.now();
//调用atTime可以传入具体时分秒,构成LocalDateTime
LocalDateTime time1 = localDate.atTime(18, 18,18);
//创建LocalTime对象
LocalTime localTime = LocalTime.now();
//调用atDate,传入具体年月日对象,构成LocalDateTime
LocalDateTime localDateTime1 = localTime.atDate(localDate);
localDateTime.equals(time1); //true

//从LocalDateTime中可以获取LocalDate和LocalTim
LocalDate date = localDateTime.toLocalDate();
LocalTime time = localDateTime.toLocalTime();

int year = localDateTime.get(ChronoField.YEAR); //localDateTime.getYear() 2019
int month = localDateTime.get(ChronoField.MONTH_OF_YEAR);//localDateTime.getMonthValue() 6
int dayOfMonth = localDateTime.get(ChronoField.DAY_OF_MONTH);//localDateTime.getDayOfMonth() 20
int hour = localDateTime.getHour();  //18
int minute = localDateTime.getMinute();  //18
int second = localDateTime.getSecond();  //18
int nano = localDateTime.getNano();  //0

日期解析与格式化

java.time.format包就是解析日期格式化日期的,最重要的是DateTimeFormatter类,支持以下标记占位符。

 * <pre>
 *  Symbol  Meaning                     Presentation      Examples
 *  ------  -------                     ------------      -------
 *   G       era                         text              AD; Anno Domini; A
 *   u       year                        year              2004; 04
 *   y       year-of-era                 year              2004; 04
 *   D       day-of-year                 number            189
 *   M/L     month-of-year               number/text       7; 07; Jul; July; J
 *   d       day-of-month                number            10
 *
 *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
 *   Y       week-based-year             year              1996; 96
 *   w       week-of-week-based-year     number            27
 *   W       week-of-month               number            4
 *   E       day-of-week                 text              Tue; Tuesday; T
 *   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
 *   F       week-of-month               number            3
 *
 *   a       am-pm-of-day                text              PM
 *   h       clock-hour-of-am-pm (1-12)  number            12
 *   K       hour-of-am-pm (0-11)        number            0
 *   k       clock-hour-of-am-pm (1-24)  number            0
 *
 *   H       hour-of-day (0-23)          number            0
 *   m       minute-of-hour              number            30
 *   s       second-of-minute            number            55
 *   S       fraction-of-second          fraction          978
 *   A       milli-of-day                number            1234
 *   n       nano-of-second              number            987654321
 *   N       nano-of-day                 number            1234000000
 *
 *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 *   z       time-zone name              zone-name         Pacific Standard Time; PST
 *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
 *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
 *
 *   p       pad next                    pad modifier      1
 *
 *   '       escape for text             delimiter
 *   ''      single quote                literal           '
 *   [       optional section start
 *   ]       optional section end
 *   #       reserved for future use
 *   {       reserved for future use
 *   }       reserved for future use
 * </pre>

他有一些预定义常量

LocalDateTime localDateTime = LocalDateTime.of(2019,6,20,18,18,18,999);
String format = localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);//2019-06-20T18:18:18.000000999
String format1 = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);//2019-06-20T18:18:18.000000999
String format2 = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSSSSSSSS"));//2019-06-20T18:18:18.000000999

LocalDateTime localDateTime1 = LocalDateTime.parse("2019-06-20T18:18:18");
LocalDateTime localDateTime2 = LocalDateTime.parse("2019-06-20 18:18:18",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

当然也可以创建一个更加复杂的解析器

DateTimeFormatter builder = new DateTimeFormatterBuilder()
        .appendText(ChronoField.DAY_OF_MONTH)   //首先解析的是一个月的第几天
        .appendLiteral("/")   //分隔符
        .appendText(ChronoField.MONTH_OF_YEAR)  //一年的第几个月
        .appendLiteral(" ")   //分隔符
        .appendText(ChronoField.YEAR)  //年份
        .parseCaseInsensitive()  //开始解析,不区分大小写
        .toFormatter(Locale.CHINA);  //按照哪个国家的方言开始解析
LocalDate date = LocalDate.of(2019, 6, 20);
String format = date.format(builder);// 20/六月 2019

时间调整

Java8提供了新的plusXxx()方法用于计算日期时间增量值,minusXxx()方法用于日期时间的减量值,withXxx()方法指定日期时间指标。

LocalDateTime localDateTime = LocalDateTime.of(2019,6,20,18,18,18);
//2020-03-28 18:06:18
LocalDateTime localDateTime1 
                = localDateTime.plusYears(1).minusMonths(3).plusDays(8).withHour(18).with(ChronoField.MINUTE_OF_HOUR,6);

TemporalAdjuster

当我们遇到复杂情况的时候,比如调整时间到下个周日之类的要求,我们就需要自定义一个TemporalAdjuster对象,更加灵活的处理日期
java8已经预定义好一些TemporalAdjuster了,可以通过工厂类访问他们

LocalDateTime localDateTime = LocalDateTime.of(2019,6,20,18,18,18);
LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));//2019-06-23 18:18:18
LocalDateTime localDateTime3 = localDateTime.with(TemporalAdjusters.lastDayOfMonth());//2019-06-30 18:18:18

定制TemporalAdjuster

创建类实现TemporalAdjuster接口

/**
 * 需求:返回下一个工作日,如果日期在周一到周五之间,就返回下一天就好,如果是周五六日就需要返回下周一的日期
 */
public class NextWorkingDay implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        //得到参数中是这周的第几天
        int day = temporal.get(ChronoField.DAY_OF_WEEK);
        //根据第几天构造出DayOfWeek枚举类,容易观察,当然也可以不用构造
        //如果不够再下面的判断相等直接改成上面的day就行了
        DayOfWeek dayOfWeek = DayOfWeek.of(day);
        //需要在参数的基础上增加几天
        int dayNeedAdd = 1;
        //如果是周五,就需要推后三天才是周一
        if (dayOfWeek == DayOfWeek.FRIDAY){
            dayNeedAdd = 3;
        }
        //如果是周六,就需要推后两天才是周一
        if (dayOfWeek == DayOfWeek.SATURDAY){
            dayNeedAdd = 2;
        }
        //如果是周日或者当天就是在周一到周五之间的,直接加一就可以,即返回下一天
        return temporal.plus(dayNeedAdd, ChronoUnit.DAYS);
    }
}

上面说此接口是函数式接口,当然就可以使用Lmabda传入了,使用如下

LocalDate date = LocalDate.of(2018, 11, 25);//周日
LocalDate nextWorkDay = date.with(new NextWorkingDay());  //2018-11-26

使用lambda

LocalDate date = LocalDate.of(2018, 11, 25);//周日
LocalDate nextWorkDay = date.with(temporal -> {
    //具体实现是把上面的实现类NextWorkingDay内实现的方法体贴进来就行了
});

也可以这样

LocalDate date = LocalDate.of(2018, 11, 25);//周日
TemporalAdjuster nextWorkDay = TemporalAdjusters.ofDateAdjuster(temporal -> {
    //具体实现是把上面的实现类NextWorkingDay内实现的方法体贴进来就行了
});
LocalDate date1 = date.with(nextWorkDay);

如上是一个静态方法,传入一个UnaryOperator函数式接口的实现即可,就能够返回一个TemporalAdjuster对象,然后传入with方法即可

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值