Java8日期及时间处理工具


https://blog.csdn.net/qq_38288606


Java8引入了一套全新的时间日期API,Java对日期、日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的。
看来Java已经意识到需要为时间及日期功能提供更好的支持了,这对已经习惯使用Joda时间日期库的社区而言也是件好事。
关于这个新的时间日期库的最大的优点就在于它定义清楚了时间日期相关的一些概念,比方说:

  • 瞬时时间(Instant)
  • 持续时间(duration)
  • 日期(date)
  • 时间(time)
  • 时区(time-zone)
  • 时间段(Period)

同时它也借鉴了Joda库的一些优点,比如将人和机器对时间日期的理解区分开的。
Java8仍然延用了ISO的日历体系,并且与它的前辈们不同,java.time包中的类是不可变且线程安全的。
新的时间及日期API位于java.time包中,下面是里面的一些关键的类:

  • Instant:它代表的是时间戳
  • LocalDate:不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。
  • LocalTime:它代表的是不含日期的时间
  • LocalDateTime:它包含了日期及时间,不过还是没有偏移信息或者说时区。
  • ZonedDateTime:这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。

新的库还增加了ZoneOffset及Zoned,可以为时区提供更好的支持。有了新的DateTimeFormatter之后日期的解析及格式化也变得焕然一新了。


package com.michael.utils;

import org.apache.commons.lang3.StringUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.TimeZone;

/**
 * 时间工具类
 * <p>
 * Created by michael on 2019/3/11.
 */
public class LocalDateTimeUtils {

    /**
     * 日期格式:yyyy-MM-dd
     */
    public static String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 日期格式:yyyyMMdd
     */
    public static String DATE_PATTERN_A = "yyyyMMdd";

    /**
     * 日期时间格式:yyyy-MM-dd HH:mm:ss
     */
    public static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 时间格式(24小时制):HH:mm:ss
     */
    public static String TIME_PATTERN_24 = "HH:mm:ss";

    /**
     * 时间格式(12小时制):hh:mm:ss
     */
    public static String TIME_PATTERN_12 = "hh:mm:ss";

    /**
     * 获取年份
     */
    public static void getYear() {
        LocalDateTime localTime = LocalDateTime.now();
        int year = localTime.get(ChronoField.YEAR);
        System.out.println(year);
    }

    /**
     * 获取月份
     */
    public static void getMonth() {
        LocalDateTime localTime = LocalDateTime.now();
        int month = localTime.get(ChronoField.MONTH_OF_YEAR);
        System.out.println(month);
    }

    /**
     * 获取某月的第几天
     */
    public static void getMonthOfDay() {
        LocalDateTime localTime = LocalDateTime.now();
        int day = localTime.get(ChronoField.DAY_OF_MONTH);
        System.out.println(day);
    }

    /**
     * 格式化日期为字符串
     *
     * @param date    需要格式化的日期
     * @param pattern 格式,如:yyyy-MM-dd
     * @return 日期字符串
     */
    public static String format(Date date, String pattern) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析字符串日期为Date
     *
     * @param dateStr 日期字符串
     * @param pattern 格式,如:yyyy-MM-dd
     * @return Date
     */
    public static Date parse(String dateStr, String pattern) {
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * 为Date增减分钟(减传负数)
     *
     * @param date    日期
     * @param minutes 要增减的分钟数
     * @return 新的日期
     */
    public static Date addReduceMinutes(Date date, Long minutes) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        LocalDateTime newDateTime = dateTime.plusMinutes(minutes);
        return Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 增加时间
     *
     * @param date date
     * @param hour 要增加的小时数
     * @return 新的日期
     */
    public static Date addHour(Date date, Long hour) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        LocalDateTime localDateTime = dateTime.plusHours(hour);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 当天的起始时间
     *
     * @return 如:Tue Jun 11 00:00:00 CST 2019
     */
    public static Date getStartTime() {
        LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        return localDateTime2Date(now);
    }

    /**
     * 当天的结束时间
     *
     * @return 如:Tue Jun 11 23:59:59 CST 2019
     */
    public static Date getEndTime() {
        LocalDateTime now = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(999);
        return localDateTime2Date(now);
    }

    /**
     * 减月份
     *
     * @param monthsToSubtract 月份
     * @return Date
     */
    public static Date minusMonths(long monthsToSubtract) {
        LocalDate localDate = LocalDate.now().minusMonths(monthsToSubtract);
        return localDate2Date(localDate);
    }

    /**
     * LocalDate类型转为Date
     *
     * @param localDate
     * @return
     */
    public static Date localDate2Date(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * LocalDateTime类型转为Date
     *
     * @param localDateTime
     * @return Date
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 查询当前年的第一天
     *
     * @param pattern 格式,如:yyyyMMdd
     * @return 20190101
     */
    public static String getFirstDayOfCurrentYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().withMonth(1).withDayOfMonth(1);
        return format(localDateTime2Date(localDateTime), StringUtils.isEmpty(pattern) ? DATE_PATTERN_A : pattern);
    }

    public static String getFirstDayOfCurrentYear() {
        LocalDateTime localDateTime = LocalDateTime.now().withMonth(1).withDayOfMonth(1);
        return format(localDateTime2Date(localDateTime), DATE_PATTERN_A);
    }

    /**
     * 查询前一年最后一个月第一天
     *
     * @param pattern 格式,如:yyyyMMdd
     * @return 20190101
     */
    public static String getLastMonthFirstDayOfPreviousYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1);
        return format(localDateTime2Date(localDateTime), StringUtils.isEmpty(pattern) ? DATE_PATTERN_A : pattern);
    }

    public static String getLastMonthFirstDayOfPreviousYear() {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1);
        return format(localDateTime2Date(localDateTime), DATE_PATTERN_A);
    }

    /**
     * 查询前一年最后一个月的最后一天
     *
     * @param pattern 格式,如:yyyyMMdd
     * @return 20190101
     */
    public static String getLastMonthLastDayOfPreviousYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).with(TemporalAdjusters.lastDayOfYear());
        return format(localDateTime2Date(localDateTime), StringUtils.isEmpty(pattern) ? DATE_PATTERN_A : pattern);
    }

    public static String getLastMonthLastDayOfPreviousYear() {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).with(TemporalAdjusters.lastDayOfYear());
        return format(localDateTime2Date(localDateTime), DATE_PATTERN_A);
    }

    /**
     * 获取当前日期
     *
     * @param pattern 格式,如:yyyy-MM-dd
     * @return 2019-01-01
     */
    public static String getCurrentDay(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return format(localDateTime2Date(localDateTime), StringUtils.isEmpty(pattern) ? DATE_PATTERN : pattern);
    }

    public static String getCurrentDay() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return format(localDateTime2Date(localDateTime), DATE_PATTERN);
    }

    /**
     * 获取时区
     */
    public static void getZone() {
        // 默认时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId.toString());

        zoneId = ZoneId.of("Asia/Shanghai");
        System.out.println(zoneId.toString());

        zoneId = TimeZone.getTimeZone("CTT").toZoneId();
        System.out.println(zoneId.toString());
    }

    /**
     * 字符串转时间
     */
    public static void strToDate() {
        LocalDate date = LocalDate.parse("20190522", DateTimeFormatter.ofPattern(DATE_PATTERN_A));
        System.out.println(date);
    }

    /**
     * 时间格式化输出
     */
    public static void dateToStr() {
        LocalDate today = LocalDate.now();
        System.out.println("当前日期:" + today.format(DateTimeFormatter.ofPattern(DATE_PATTERN)));
        System.out.println();

        LocalTime time = LocalTime.now();
        //24小时制
        System.out.println("当前时间(24小时制):" + time.format(DateTimeFormatter.ofPattern(TIME_PATTERN_24)));
        //12小时制
        System.out.println("当前时间(12小时制):" + time.format(DateTimeFormatter.ofPattern(TIME_PATTERN_12)));
        System.out.println();

        LocalDateTime now = LocalDateTime.of(today, time);
        //yyyyMMdd
        System.out.println(now.format(DateTimeFormatter.BASIC_ISO_DATE));
        //yyyy-MM-dd
        System.out.println(now.format(DateTimeFormatter.ISO_DATE));
        System.out.println();

        //2019-05-28T15:30:21.047
        System.out.println(now.format(DateTimeFormatter.ISO_DATE_TIME));
        //local date
        System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));
        //local time 带毫秒 eg:15:33:00.043
        System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME));
        //local dateTime eg:2019-05-28T15:33:00.043
        System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        //2019-W22-2
        System.out.println(now.format(DateTimeFormatter.ISO_WEEK_DATE));
    }

    /**
     * Date 与 Localdatetime 的转换
     */
    public static void transformWithDate() {
        // date 转 localdatetime
        Date date = new Date();
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println(localDateTime);
        // localdatetime 转 date
        Date date1 = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
        System.out.println(date1);
    }

    /**
     * 与时间戳的转换
     */
    public static void transformWithTimestamp() {
        //秒级时间戳
        long timeStamp = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
        System.out.println("秒级时间戳:" + timeStamp);
        timeStamp = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
        System.out.println("秒级时间戳:" + timeStamp);
        System.out.println("秒级时间戳转时间:" + Instant.ofEpochSecond(timeStamp).atZone(ZoneId.systemDefault()).toLocalDateTime());
        System.out.println();
        //毫秒级时间戳
        timeStamp = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        System.out.println("毫秒级时间戳:" + timeStamp);
        System.out.println("毫秒级时间戳转时间:" + Instant.ofEpochMilli(timeStamp).atZone(ZoneId.systemDefault()).toLocalDateTime());
    }

    /**
     * 时间调整到特定某天
     */
    public static void adjust() {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前时间:" + now);
        //同月的第一天
        LocalDateTime firstDayInSameMonthOfNow = now.withDayOfMonth(1);
        System.out.println("同月的第一天:" + firstDayInSameMonthOfNow);
        //同年的第一天
        LocalDateTime firstDayInSameYearOfNow = now.withDayOfYear(1);
        System.out.println("同年的第一天:" + firstDayInSameYearOfNow);
        //同年的第2月第10天
        LocalDateTime time = now.withMonth(2).withDayOfMonth(10);
        System.out.println("同年的第2月第10天:" + time);
        //当天的6点整
        time = now.withHour(6).withMinute(0).withSecond(0).withNano(0);
        System.out.println("当天的6点整:" + time);
    }

    /**
     * 格式化时间-默认yyyy-MM-dd HH:mm:ss格式
     *
     * @param dateTime LocalDateTime对象
     * @param pattern  要格式化的字符串
     * @return
     */
    public static String formatDateTime(LocalDateTime dateTime, String pattern) {
        if (dateTime == null) {
            return null;
        }
        return dateTime.format(DateTimeFormatter.ofPattern(StringUtils.isEmpty(pattern) ? DATE_TIME_PATTERN : pattern));
    }

    public static String formatDateTime(LocalDateTime dateTime) {
        return formatDateTime(dateTime, DATE_TIME_PATTERN);
    }

    /**
     * 获取某天的00:00:00
     *
     * @param dateTime
     * @return
     */
    public static String getDayStart(LocalDateTime dateTime) {
        return formatDateTime(dateTime.with(LocalTime.MIN));
    }

    public static String getDayStart() {
        return getDayStart(LocalDateTime.now());
    }

    /**
     * 获取某天的23:59:59
     *
     * @param dateTime
     * @return
     */
    public static String getDayEnd(LocalDateTime dateTime) {
        return formatDateTime(dateTime.with(LocalTime.MAX));
    }

    public static String getDayEnd() {
        return getDayEnd(LocalDateTime.now());
    }

    /**
     * 获取某月第一天的00:00:00
     *
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static String getFirstDayOfMonth(LocalDateTime dateTime) {
        return formatDateTime(dateTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN));
    }

    public static String getFirstDayOfMonth() {
        return getFirstDayOfMonth(LocalDateTime.now());
    }

    /**
     * 获取某月最后一天的23:59:59
     *
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static String getLastDayOfMonth(LocalDateTime dateTime) {
        return formatDateTime(dateTime.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX));
    }

    public static String getLastDayOfMonth() {
        return getLastDayOfMonth(LocalDateTime.now());
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352