JAVA8时间处理学习笔记

一、Java8 日期处理

参考资料: https://mp.weixin.qq.com/s/xAPik92FU37Ap2PRiUIPyw

1.LocalDate(yyyy-MM-dd)

1.1.获取今天日期

Java 8 中的 LocalDate 用于表示当天日期,比如: 今天的日期2022-08-12 ,格式是yyyy-MM-dd

    /**
     * <h2>获取今天的日期(只有年月日)</h2>
     */
    @Test
    public void getCurrentLocalDate() {
        log.info("今天的日期:" + LocalDate.now());
        //今天的日期:2022-08-12
        //可以用于做链路追踪
        MDC.put("xx", "1000112234343");
    }

1.2.获取年-月-日

    private LocalDate today;

    @Before
    public void init() {
        log.info("单元测试初始化~~~~~~");
        today = LocalDate.now();
    }

	/**
     * <h2>获取年</h2>
     */
    @Test
    public void getYear() {
        int year = today.getYear();
        log.info("当前时间:{},获取年:{}", today, year);
        //当前时间:2022-08-12,获取年:2022
    }

    /**
     * <h2>获取月</h2>
     */
    @Test
    public void getMonth() {
        Month month = today.getMonth();
        int value = month.getValue();
        //或者直接调用 getMonthValue() 得到对应的值
        int monthValue = today.getMonthValue();
        log.info("当前时间:{},获取月:{},value:{}", today, month, value);
        //当前时间:2022-08-12,获取月:AUGUST,value:8
    }

    /**
     * 获取日
     */
    @Test
    public void getDay() {
        int dayOfMonth = today.getDayOfMonth();
        log.info("当前时间:{},获取日:{}", today, dayOfMonth);
    }

1.3.指定日期处理

通过静态工厂方法 now(),创建了当天日期;还可以调用另一个有用的工厂方法 LocalDate.of() 创建任意日期, 该方法需要传入年、月、日做参数,返回对应的 LocalDate 实例。

    /**
     * <h2>处理待定日期</h2>
     */
    @Test
    public void undeterminedDay() {
        //java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 33
        //LocalDate of = LocalDate.of(2022, 2, 33);

        //java.time.DateTimeException: Invalid date 'FEBRUARY 31'
        //LocalDate of = LocalDate.of(2022, 2, 31);

        //java.time.DateTimeException: Invalid date 'FEBRUARY 30'
        //LocalDate of = LocalDate.of(2022, 2, 30);

        //java.time.DateTimeException: Invalid date 'February 29' as '2022' is not a leap year
        //LocalDate of = LocalDate.of(2022, 2, 29);

        LocalDate of = LocalDate.of(2022, 2, 28);
        //自定义时间:2022-02-28,年:2022,月:2,日:28,所属星期几:1
        log.info("自定义时间:{},年:{},月:{},日:{},所属星期几:{}", of, of.getYear(), of.getMonthValue(), of.getDayOfMonth(), of.getDayOfWeek().getValue());

        LocalDate of2 = LocalDate.of(2022, 2, 27);
        int value = of2.getDayOfWeek().getValue();
        //自定义时间:2022-02-27,所属星期几:7
        log.info("自定义时间:{},所属星期几:{}", of2, value);


        LocalDate of3 = LocalDate.of(2022, 2, 26);
        int value2 = of3.getDayOfWeek().getValue();
        //自定义时间:2022-02-26,所属星期几:6
        log.info("自定义时间:{},所属星期几:{}", of3, value2);

        LocalDate now = LocalDate.now();
        int dayOfYear = now.getDayOfYear();
        //当前时间:2022-08-12,在这年中属于第几天:224
        log.info("当前时间:{},在这年中属于第几天:{}", now, dayOfYear);
    }

1.4.获取指定时间的所属的季度

    /**
     * <h2>获取季度</h2>
     */
    @Test
    public void getQuarter(){
        //LocalDate start = LocalDate.now();
        LocalDate start = LocalDate.of(2022,6,7);
        int quarter = (start.getMonthValue()-1)/3 + 1;
        //当前时间:2022-06-07,所属季度:2
        log.info("当前时间:{},所属季度:{}",start,quarter);
    }

1.5.比较2个时间是否相等

    /**
     * <h2>比较2个时间是否相等</h2>
     * LocalDate 格式是: 'yyyy-MM-dd' 年月日
     */
    @Test
    public void isEquals2Day() {
        LocalDate one = LocalDate.now();
        LocalDate tow = LocalDate.now();
        //第一个时间:2022-08-12,第二个时间:2022-08-12相等
        if (one.equals(tow)) {
            log.info("第一个时间:{},第二个时间:{}相等", one, tow);
        } else {
            log.info("第一个时间:{},第二个时间:{}不相等", one, tow);

        }
    }

1.6.检查像生日这种周期性事件

只要当天的日期和生日匹配,无论是哪一年都会打印出祝贺信息。

    /**
     * 检查像生日这种周期性事件
     */
    @Test
    public void periodDay() {
        LocalDate date1 = LocalDate.now();
        LocalDate date2 = LocalDate.of(2018, 8, 12);

        MonthDay birthday = MonthDay.of(date2.getMonth(), date2.getDayOfMonth());
        MonthDay currentMonthDay = MonthDay.from(date1);
        
        if (currentMonthDay.equals(birthday)) {
            log.info("是你的生日");
        } else {
            log.info("你的生日还没有到");
        }
    }

1.7 LocalDate增加时间

LocalDate 日期不包含时间信息,它的 plus() 方法用来增加天、周、月

    /**
     * <h2>计算一周后的日期</h2>
     */
    @Test
    public void addWeek(){
        LocalDate today = LocalDate.now();
        //今天的日期为:2022-08-12
        log.info("今天的日期为:"+today);
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        //一周后的日期为:2022-08-19
        log.info("一周后的日期为:"+nextWeek);
        log.info("--------------------------><------------------------------");
        LocalDate localDate = today.plusDays(2);
        //当前时间:2022-08-12,增加2天:2022-08-14
        log.info("当前时间:{},增加2天:{}",today,localDate);

        LocalDate localDate1 = today.plusYears(1);
        //当前时间:2022-08-12,增加1年:2023-08-12
        log.info("当前时间:{},增加1年:{}",today,localDate1);

        LocalDate localDate2 = today.plusMonths(1);
        //当前时间:2022-08-12,增加1月:2022-09-12
        log.info("当前时间:{},增加1月:{}",today,localDate2);

        LocalDate localDate3 = today.plusWeeks(2);
        //当前时间:2022-08-12,增加2周:2022-08-26
        log.info("当前时间:{},增加2周:{}",today,localDate3);
    }

1.8 计算一年前或一年后的日期

利用 minus() 方法计算一年前的日期

LocalDate today = LocalDate.now();

LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("一年前的日期 : " + previousYear);

LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("一年后的日期:"+nextYear);

1.9 Clock 时钟类

Clock 时钟类用于获取当时的时间戳,或当前时区下的日期时间信息

//以前用到 System.currentTimeInMillis()
// 和 TimeZone.getDefault() 的地方都可用 Clock 替换。
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock.millis());

// Returns time based on system clock zone
Clock defaultClock = Clock.systemDefaultZone();
System.out.println("Clock : " + defaultClock.millis());

1.10 判断日期是早于还是晚于另一个日期

如何判断给定的一个日期是大于某天还是小于某天

LocalDate 类有两类方法 isBefore() 和 isAfter() 用于比较日期。调用 isBefore() 方法时,如果给定日期小于当前日期则返回 true。

LocalDate today = LocalDate.now();

LocalDate tomorrow = LocalDate.of(2018,2,6);
if(tomorrow.isAfter(today)){
    System.out.println("之后的日期:"+tomorrow);
}

LocalDate yesterday = today.minus(1, ChronoUnit.DAYS);
if(yesterday.isBefore(today)){
    System.out.println("之前的日期:"+yesterday);
}

1.11 计算两个日期之间的天数和月数

有一个常见日期操作是计算两个日期之间的天数、周数或月数。在 Java 8 中可以用 java.time.Period 类来做计算。

计算了当天和将来某一天之间的月数:

LocalDate today = LocalDate.now();

LocalDate java8Release = LocalDate.of(2018, 12, 14);

Period periodToNextJavaRelease = Period.between(today, java8Release);
System.out.println("Months left between today and Java 8 release : "
                   + periodToNextJavaRelease.getMonths() );

1.12 获取当前的时间戳

Instant 类有一个静态工厂方法 now() 会返回当前的时间戳;时间戳信息里同时包含了日期和时间,这和 java.util.Date 很像。实际上 Instant 类确实等同于 Java 8 之前的 Date 类,你可以使用 Date 类和 Instant 类各自的转换方法互相转换。例如:Date.from(Instant) 将 Instant 转换成 java.util.Date,Date.toInstant() 则是将 Date 类转换成 Instant 类。

Instant timestamp = Instant.now();
System.out.println("What is value of this instant " + timestamp.toEpochMilli());

1.13 时间格式化

String dayAfterTommorrow = "20180205";
LocalDate formatted = LocalDate.parse(dayAfterTommorrow,
                                      DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dayAfterTommorrow+"  格式化后的日期为:  "+formatted);
LocalDateTime date = LocalDateTime.now();

DateTimeFormatter format1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//日期转字符串
String str = date.format(format1);

System.out.println("日期转换为字符串:"+str);

DateTimeFormatter format2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//字符串转日期
LocalDate date2 = LocalDate.parse(str,format2);
System.out.println("日期类型:"+date2);

2.LocalTimeTest (HH:mm:ss)

2.1 获取当前时间的小时分钟

    /**
     * 获取当前时间小时、分钟、秒
     */
    @Test
    public void getHouseMinuteSecond() {
        //获取系统的当前小时、分钟、秒,同时可以设置时区
        LocalTime now = LocalTime.now();
        //获取当前的时间,不含有日期:11:05:13.249
        log.info("获取当前的时间,不含有日期:" + now);
    }

2.2 获取当前时间

通过增加小时、分、秒来计算将来的时间;Java 8 除了不变类型和线程安全的好处之外,还提供了更好的 plusHours() 方法替换 add(),并且是兼容的

**注意:**这些方法返回一个全新的 LocalTime 实例,由于其不可变性,返回后一定要用变量赋值

    /**
     * <h2>增加小时、分、秒来计算将来的时间</h2>
     */
    @Test
    public void getFutureDayInfo(){
        LocalTime now = LocalTime.now();
        LocalTime localTime = now.plusHours(3);
        //当前时间信息:11:21:12.972,增加3个小时:14:21:12.972
        log.info("当前时间信息:{},增加3个小时:{}",now,localTime);

        LocalTime localTime1 = now.plusMinutes(20);
        //当前时间信息:11:21:12.972,增加20分钟:11:41:12.972
        log.info("当前时间信息:{},增加20分钟:{}",now,localTime1);

        LocalTime localTime2 = now.plusSeconds(10);
        //当前时间信息:11:21:12.972,增加10秒:11:21:22.972
        log.info("当前时间信息:{},增加10秒:{}",now,localTime2);
    }

2.3 计算一周后的日期

计算一周后的日期:

  • LocalDate 日期不包含时间信息,它的 plus() 方法用来增加天、周、月
  • ChronoUnit 类声明了这些时间单位。由于 LocalDate 也是不变类型,返回后一定要用变量赋值。```
    /**
     * <h2>计算一周后的日期</h2>
     */
    @Test
    public void addWeek(){
        LocalDate today = LocalDate.now();
        //今天的日期为:2022-08-12
        log.info("今天的日期为:"+today);
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        //一周后的日期为:2022-08-19
        log.info("一周后的日期为:"+nextWeek);
    }

3.LocalDateTime(yyyy-MM-dd HH:mm:ss)

3.1 处理时区

单独的类如 ZoneId 来处理特定时区,ZoneDateTime 类来表示某时区下的时间

// Date and time with timezone in Java 8
ZoneId america = ZoneId.of("America/New_York");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime dateAndTimeInNewYork  = ZonedDateTime.of(localtDateAndTime, america );
System.out.println("Current date and time in a particular timezone : " + dateAndTimeInNewYork);
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")

3.2 信用卡到期这类固定日期

YearMonth与 MonthDay 检查重复事件的例子相似,YearMonth 是另一个组合类,用于表示信用卡到期日、FD 到期日、期货期权到期日等。

还可以用这个类得到当月共有多少天,YearMonth 实例的 lengthOfMonth() 方法可以返回当月的天数,在判断 2 月有 28 天还是 29 天时非常有用。

YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2019, Month.FEBRUARY);
System.out.printf("Your credit card expires on %s %n", creditCardExpiry);

3.3 检查闰年

LocalDate today = LocalDate.now();
if(today.isLeapYear()){
    System.out.println("This year is Leap year");
}else {
    System.out.println("2018 is not a Leap year");
}

4.时间扩展工具类

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <!--            <version>5.7.22</version>-->
    <version>5.8.0.M4</version>
</dependency>
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import org.springframework.util.StringUtils;

import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * 日期扩展工具类
 *
 * @author TOM
 * @date 2022/5/05
 */
public class DateUtilsExt {


    /**
     * 获取当月第一天
     */
    private static LocalDateTime getFirstLocalDayOfMonth(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
    }

    /**
     * 获取当月第一周  以第一个周一为准
     */
    private static LocalDateTime getFirstMonday(LocalDateTime sourceTime) {
        LocalDateTime firstMondayOfMonth = getFirstLocalDayOfMonth(sourceTime);
        for (int i = 0; i < 6; i++) {
            DayOfWeek dayOfWeekTemp = firstMondayOfMonth.getDayOfWeek();
            if (dayOfWeekTemp.equals(DayOfWeek.MONDAY)) {
                break;
            }
            //往后推一天
            firstMondayOfMonth = firstMondayOfMonth.plusDays(1);
        }
        return firstMondayOfMonth;
    }

    /**
     * 字符串转换成LocalDateTime
     *
     * @param dateStr     时间字符串
     * @param datePattern 默认时间格式:yyyy-MM-dd HH:mm:ss
     *                    时间字符串格式: yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss
     */
    public static LocalDateTime strConverToLocalDateTime(String dateStr, String datePattern) {
        if (StringUtils.isEmpty(datePattern)) {
            datePattern = "yyyy-MM-dd HH:mm:ss";
        }
        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(datePattern));
    }

    /**
     * 获取几月份的第几周 [X月份第X周]
     */
    public static String getMonthNoAndWeekNoInfo(LocalDateTime sourceTime) {
        String monthNoAndWeekNo;
        //获取当月的第一天
        //获取月第一个周一,从当月第一天开始找

        LocalDateTime firstMondayOfMonth = getFirstMonday(sourceTime);

        //比较当月的第一个星期一 < = 参数时间
        if (firstMondayOfMonth.isBefore(sourceTime) || firstMondayOfMonth.isEqual(sourceTime)) {
            //当月第一个周一在当前时间之前 firstMondayOfMonth<=sourceTime
            //计算两个时间间隔天数
            int dayOfMonthFirstMonday = firstMondayOfMonth.getDayOfMonth();
            int dayOfMonthSourceTime = sourceTime.getDayOfMonth();

            int diffDays = dayOfMonthSourceTime - dayOfMonthFirstMonday;
            //第几周weekNo
            int weekNo = (diffDays / 7) + 1;
            //月份
            int monthNo = sourceTime.getMonth().getValue();

            monthNoAndWeekNo = monthNo + "月份" + "第" + weekNo + "周";
        } else {
            //如果当月的第一个周一大于参数时间,则要计算到上个月份去
            //获取上一个月的第一个周一
            LocalDateTime lastMontLocalDateTime = sourceTime.minusMonths(1);
            //上个月的第一天
            //从上个月的第一天开始找周一
            LocalDateTime firstMondayOfMonthLast = getFirstMonday(lastMontLocalDateTime);

            //  计算两个时间间隔天数 (上月第一个周一 减去 当前时间)
            Duration duration = Duration.between(firstMondayOfMonthLast, sourceTime);
            long diffDays = duration.toDays(); //相差的天数
            //第几周weekNo
            long weekNo = (diffDays / 7) + 1;
            //月份
            int monthNo = firstMondayOfMonthLast.getMonth().getValue();//汉字版月份

            monthNoAndWeekNo = monthNo + "月份" + "第" + weekNo + "周";
        }

        return monthNoAndWeekNo;
    }


    private static Long getMonthNoAndWeekNo(LocalDateTime sourceTime) {
        long weekNo;
        //获取当月的第一天
        //获取月第一个周一,从当月第一天开始找

        LocalDateTime firstMondayOfMonth = getFirstMonday(sourceTime);

        //比较当月的第一个星期一 < = 参数时间
        if (firstMondayOfMonth.isBefore(sourceTime) || firstMondayOfMonth.isEqual(sourceTime)) {
            //当月第一个周一在当前时间之前 firstMondayOfMonth<=sourceTime
            //计算两个时间间隔天数
            int dayOfMonthFirstMonday = firstMondayOfMonth.getDayOfMonth();
            int dayOfMonthSourceTime = sourceTime.getDayOfMonth();

            int diffDays = dayOfMonthSourceTime - dayOfMonthFirstMonday;
            //第几周weekNo
            weekNo = (diffDays / 7) + 1;

        } else {
            //如果当月的第一个周一大于参数时间,则要计算到上个月份去
            //获取上一个月的第一个周一
            LocalDateTime lastMontLocalDateTime = sourceTime.minusMonths(1);
            //上个月的第一天
            //从上个月的第一天开始找周一
            LocalDateTime firstMondayOfMonthLast = getFirstMonday(lastMontLocalDateTime);

            //  计算两个时间间隔天数 (上月第一个周一 减去 当前时间)
            Duration duration = Duration.between(firstMondayOfMonthLast, sourceTime);
            long diffDays = duration.toDays(); //相差的天数
            //第几周weekNo
            weekNo = (diffDays / 7) + 1;

        }

        return weekNo;
    }
    //-------------------------------------------------------------------

    /**
     * 时间转换成LocalDateTime
     *
     * @param date java.util.Date
     * @return LocalDateTime
     */
    public static LocalDateTime dateConverLocalDateTime(Date date) {
        DateTime dt = DateUtil.date(date);
        // Date对象转换为LocalDateTime
        LocalDateTime of = LocalDateTimeUtil.of(dt);
        return of;

    }

    /**
     * 获取年月日  yyyy-MM-dd
     */
    public static String getYearMonthDay(Date date) {
        return DateUtil.format(date, "yyyy-MM-dd");
    }

    /**
     * 获得年的部分
     *
     * @param date java.util.Date
     * @return 年份
     */
    public static int getYear(Date date) {
        //获得年的部分
        return DateUtil.year(date);
    }

    /**
     * 获取月
     *
     * @param date java.util.Date
     * @return 月份
     */
    public static int getMonth(Date date) {
        //获得月份,从0开始计数
        return DateUtil.month(date) + 1;
    }

    /**
     * 获取日部分
     */
    public static int getDayofMonth(Date date) {
        return dateConverLocalDateTime(date).getDayOfMonth();
    }

    /**
     * 获得指定日期的小时数部分
     */
    public static int getHouse(Date date) {
        return DateUtil.hour(date, true);
    }

    /**
     * 获取指定日期的分钟数部分
     */
    public static int getMinute(Date date) {

        return DateUtil.minute(date);
    }

    /**
     * 获取指定日期的秒部分
     */
    public static int getSecond(Date date) {
        return DateUtil.second(date);
    }

    /**
     * 获得指定日期是所在月份的第几周
     */
    public static Long getWeekOfMonth(Date date) {
        return getMonthNoAndWeekNo(dateConverLocalDateTime(date));
    }

    /**
     * 获得指定日期所属季度,从1开始计数
     *
     * @return 第几个季度
     */
    public static int getQuarter(Date date) {
        return DateUtil.quarter(date);
    }

    /**
     * 当前时间是星期几
     * 获得指定日期是星期几,0表示周日,1表示周一
     */
    public static int getWeek(Date date){
        return DateUtil.dayOfWeek(date)-1;
    }

    /**
     * 指定时间的前一天
     */
    public static Date beforeDate(Date date){
        return  DateUtil.offsetDay(date, -1).toJdkDate();
    }


    /**
     * 时间格式化
     */
    public static String dateFormate(Date date,String patterStr){
        String format = DateUtil.format(date, patterStr);
        return format;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值