Bootstrap

Java中的日期类

 日期和时间的格式化编码

字母描述示例
G纪元标记AD
y四位年份2001
M月份July or 07
d一个月的日期10
h A.M./P.M. (1~12)格式小时12
H一天中的小时 (0~23)22
m分钟数30
s秒数55
S毫秒数234
E星期几Tuesday
D一年中的日子360
F一个月中第几周的周几2 (second Wed. in July)
w一年中第几周40
W一个月中第几周1
aA.M./P.M. 标记PM
k一天中的小时(1~24)24
K A.M./P.M. (0~11)格式小时10
z时区Eastern Standard Time
'文字定界符Delimiter
"单引号`

Date

        java.util 包提供了 Date 类来封装当前的日期和时间。

获取时间

        Date类提供了两个构造方法,无参构造方法返回当前时间,有参构造方法需要提供一个参数,该参数是从1970年1月1日返回的毫秒值。

// 无参构造方法
// 返回当前时间 CST格式
Date date1 = new Date();
System.out.println(date1); // Fri Dec 22 10:24:12 CST 2023

Thread.sleep(1000);

Date date2 = new Date();
System.out.println(date2); // Fri Dec 22 10:24:12 CST 2023

// 返回自1970年1月1日经历的毫秒数
long currentTimeMillis = System.currentTimeMillis();
System.out.println(currentTimeMillis); // 1703211853991

// 有参构造方法
Date date = new Date(currentTimeMillis);
System.out.println(date); // Fri Dec 22 10:29:19 CST 2023

日期比较

        Date类提供了compareTo、equals、before、after方法用来进行日期的比较。

// 比较两个日期
int i = date1.compareTo(date2);
System.out.println(i); // -1

boolean before = date1.before(date2);
System.out.println(before); // true

boolean after = date1.after(date2);
System.out.println(after); // false

boolean equals = date1.equals(date2);
System.out.println(equals); // false

格式化日期

        使用SimpleDateFormat进行日期的格式化,可以把Date类型的日期转换为指定格式的String类型。

 // 使用SimpleDateFormat格式化日期
 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
 String format1 = format.format(date1);
 System.out.println(format1); // 2023-12-22

 String dateString = "2023-12-23";
 Date date3 = format.parse(dateString);
 System.out.println(date3); // Sat Dec 23 00:00:00 CST 2023

 format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 String format2 = format.format(date2);
 System.out.println(format2); // 2023-12-22 10:29:19

 dateString = "2023-12-23 10:24:56";
 Date date4 = format.parse(dateString);
 System.out.println(date4); // Sat Dec 23 10:24:56 CST 2023

获取当前日期的信息

 int year = date1.getYear(); // 123 年
 int month = date1.getMonth(); // 11 月
 int datee = date1.getDate(); // 22 日
 int hours = date1.getHours(); // 10 时
 int minutes = date1.getMinutes(); // 29 分
 int seconds = date1.getSeconds(); // 19 秒
 int day = date1.getDay(); // 5 星期

        Date类提供了一系列的get方法,方便我们获取信息,但是年、月怎么都不对,在源码中,getYear()方法 减去了1900,getMonth() 也是如此,返回了一个0-11的值,同时注释也提示建议使用Calendar类中相关方法,说明该方法已经过期了。

    /**
     * Returns a value that is the result of subtracting 1900 from the
     * year that contains or begins with the instant in time represented
     * by this <code>Date</code> object, as interpreted in the local
     * time zone.
     *
     * @return  the year represented by this date, minus 1900.
     * @see     java.util.Calendar
     * @deprecated As of JDK version 1.1,
     * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
     */
    @Deprecated
    public int getYear() {
        return normalize().getYear() - 1900;
    }

Calendar

       Calendar类是 java.util 包中的一个抽象类,用于对日期和时间进行操作和格式化。它是Java中的日历类,可以用来获取和设置日期和时间的各个部分,以及执行一些常见的日期和时间操作,如计算两个日期之间的差值、比较日期的大小等。

Calendar类对象字段类型

常量描述
Calendar.YEAR年份
Calendar.MONTH月份
Calendar.DATE日期
Calendar.DAY_OF_MONTH日期,和上面的字段意义完全相同
Calendar.HOUR12小时制的小时
Calendar.HOUR_OF_DAY24小时制的小时
Calendar.MINUTE分钟
Calendar.SECOND
Calendar.DAY_OF_WEEK星期几

获取时间

        通过调用 getInstance() 方法来获取默认时区和区域设置的 Calendar 对象,调用getTime() 就能获取当前时间。

   Calendar calendar = Calendar.getInstance();

   Date now = calendar.getTime();
   System.out.println(now); // Fri Dec 22 10:57:31 CST 2023

获取当前日期的信息 

        通过调用 get() 提供上面表格中的常量作为参数,就能获取对应信息。

 int year = calendar.get(Calendar.YEAR); // 2023 年
 int month = calendar.get(Calendar.MONTH) + 1; // 12 月
 int date = calendar.get(Calendar.DATE); // 22 日
 int hour = calendar.get(Calendar.HOUR_OF_DAY); // 10 时
 int minute = calendar.get(Calendar.MINUTE); // 57 分
 int second = calendar.get(Calendar.SECOND); // 31 秒
 int day = calendar.get(Calendar.DAY_OF_WEEK); // 6 星期 这个与Date类是不同的:1代表星期日、2代表星期1、3代表星期二,以此类推。

设置指定日期

set

        调用 set(int field,int value) 利用字段类型设置指定时间。

// 设置指定日期
calendar.set(Calendar.YEAR, 2023);
calendar.set(Calendar.MONTH, Calendar.DECEMBER);
calendar.set(Calendar.DAY_OF_MONTH, 23);
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 8);
calendar.set(Calendar.SECOND, 45);

Date date1 = calendar.getTime();
System.out.println(date1); // Sat Dec 23 11:08:45 CST 2023

        这里的月份可以使用Calendar提供的的常量,也是可以使用 0-11,月份从0开始。

add

        调用 add(int field,int value),用于将当前日期加上指定日期。

  // 加上指定日期
  calendar.add(Calendar.MONTH,-1);
  calendar.add(Calendar.DATE,5);
  
  Date date2 = calendar.getTime();
  System.out.println(date2); // Tue Nov 28 11:08:45 CST 2023

获取月的第一天和最后一天

 Calendar calendar = Calendar.getInstance();
 
 // 获取当前时间
 Date now = calendar.getTime();
 System.out.println(now); // Fri Dec 22 11:29:34 CST 2023

 // 设置当月的第一天
 calendar.set(Calendar.DAY_OF_MONTH,1);
 Date firstDay = calendar.getTime();
 System.out.println(firstDay); // Fri Dec 01 11:29:34 CST 2023

 // 设置月份为下个月 当前时间为下个月第一天
 calendar.add(Calendar.MONTH,1);
 // 天数-1
 calendar.add(Calendar.DATE,-1);
 Date lastDay = calendar.getTime();
 System.out.println(lastDay); // Sun Dec 31 11:29:34 CST 2023

获取月的天数

         Calendar提供 getActualMaximum(int field) 返回当前日期,给定字段的最大值,,可以指定获取最大值的字段,如Calendar.DAY_OF_MONTH、Calendar.YEAR等。

 // 获取指定月的天数
 Calendar calendar = Calendar.getInstance();
 calendar.set(Calendar.YEAR,2024);
 calendar.set(Calendar.MONTH, Calendar.FEBRUARY); // 设置月份为二月
 int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

 System.out.println(daysInMonth); // 29

获取当前周的周一和周日

  Calendar calendar = Calendar.getInstance();
  // 获取当前时间
  Date now = calendar.getTime();
  System.out.println(now); // Fri Dec 22 11:34:37 CST 2023 

  // 设置为周一
  calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
  Date firstDayOfWeek = calendar.getTime();
  System.out.println(firstDayOfWeek); // Mon Dec 18 11:34:37 CST 2023

  // 周日
  calendar.add(Calendar.DAY_OF_WEEK, 6);
  Date lastDayOfWeek = calendar.getTime();
  System.out.println(lastDayOfWeek); // Sun Dec 24 11:34:37 CST 2023

判断是否是闰年

GregorianCalendar是Calendar类的一个具体实现。使用 isLeapYear() 直接判断是否闰年。

     // 判断是否是闰年
     int year = 2023;
     GregorianCalendar gregorianCalendar = new GregorianCalendar();

     // 测试当前年份是否为闰年
     if(gregorianCalendar.isLeapYear(year)) {
         System.out.println("当前年份是闰年");
     }
     else {
         System.out.println("当前年份不是闰年");
     }

Java8特性-日期时间

Java8 新增的日期类主要有三个:

  • LocalDate:表示日期(年月日)
  • LocalTime:表示时间(时分秒)
  • LocalDateTime:表示时间+ 日期 (年月日时分秒),是Java8最常用的日期类

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。

  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

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

Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

  • Local(本地) − 简化了日期时间的处理,没有时区的问题。

  • Zoned(时区) − 通过制定的时区处理日期时间。

新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

获取时间

 // 获取当前日期
 LocalDate localDate = LocalDate.now();
 System.out.println(localDate); // 2023-12-22

 // 获取当前时间
 LocalTime localTime = LocalTime.now();
 System.out.println(localTime); // 14:41:35.629

 // 获取当前日期时间
 LocalDateTime localDateTime = LocalDateTime.now();
 System.out.println(localDateTime); // 2023-12-22T14:41:35.629

 // LocalDate和LocalTime创建LocalDateTime
 LocalDateTime time = LocalDateTime.of(localDate, localTime);
 System.out.println(time); // 2023-12-22T14:41:35.629

格式化日期

        使用 DateTimeFormatter 重置时间格式。

 // 日期格式化
 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

 LocalDateTime localDateTime1 = LocalDateTime.now();
 System.out.println(localDateTime); // 2023-12-22T14:57:48.179

 String dateTimeStr1 = localDateTime.format(dateTimeFormatter);
 System.out.println(dateTimeStr); // 2023-12-22 14:57:48

 String dateTimeStr2 = "2023-12-22 15:03:22";
 LocalDateTime localDateTime2 = LocalDateTime.parse(dateTimeStr2,dateTimeFormatter);
 System.out.println(localDateTime2); // 2023-12-22T15:03:22

获取当前日期的信息

// 获取当前信息
LocalDateTime now = LocalDateTime.now();
System.out.println(now); // 2023-12-22T15:10:46.551

int year = now.getYear(); // 2023
int month = now.getMonthValue(); // 12
int day = now.getDayOfMonth(); // 22
       
int hour = now.getHour(); // 15
int minute = now.getMinute(); // 10
int second = now.getSecond(); // 46

int dayOfYear = now.getDayOfYear(); // 356
int dayOfWeek = now.getDayOfWeek().getValue(); // 5

获取指定日期

        TemporalAdjusters 类是Java 8引入的日期时间库中的一个类,它提供了一系列静态方法,用于执行复杂的日期时间操作。

// 获取指定日期
LocalDateTime now = LocalDateTime.now();
System.out.println(now); // 2023-12-22T15:32:45.055
        
// 获取当月第一天
LocalDateTime firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(firstDayOfMonth); // 2023-12-01T15:32:45.055

// 获取当月最后一天
LocalDateTime lastDayOfMonth = now.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDayOfMonth); // 2023-12-31T15:32:45.055

// 获取当年第一天
LocalDateTime firstDayOfYear = now.with(TemporalAdjusters.firstDayOfYear());
System.out.println(firstDayOfYear); // 2023-01-01T15:32:45.055

// 获取当年最后一天
LocalDateTime lastDayOfYear = now.with(TemporalAdjusters.lastDayOfYear());
System.out.println(lastDayOfYear); // 2023-12-31T15:32:45.055

// 获取下一年的第一天
LocalDateTime firstDayOfNextYear = now.with(TemporalAdjusters.firstDayOfNextYear());
System.out.println(firstDayOfNextYear); // 2024-01-01T15:32:45.055

// 获取当月第一个周一
LocalDateTime firstMondayOfMonth = now.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
System.out.println(firstMondayOfMonth); // 2023-12-04T15:32:45.055

// 获取当月最后一个周日
LocalDateTime lastSundayOfMonth = now.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
System.out.println(lastSundayOfMonth); // 2023-12-31T15:32:45.055

日期计算

        使用 plus(long amountToAdd , TemporalUnit unit) 可以计算指定时间后的日期。

        ChronoUnit是TemporalUnit的实现类,提供了一系列枚举值。

 LocalDateTime now = LocalDateTime.now();
 System.out.println(now); // 2023-12-22T15:44:06.356

 // 计算1天后的日期
 LocalDateTime oneDayAfter = now.plus(1, ChronoUnit.DAYS);
 System.out.println(oneDayAfter); // 2024-12-22T15:44:06.356

 // 计算1周后的日期
 LocalDateTime oneWeekAfter = now.plus(1, ChronoUnit.WEEKS);
 System.out.println(oneWeekAfter); // 2024-01-22T15:44:06.356

 // 计算1月后的日期
 LocalDateTime oneMonthAfter = now.plus(1, ChronoUnit.MONTHS);
 System.out.println(oneMonthAfter); // 2023-12-29T15:44:06.356

 // 计算1年后的日期
 LocalDateTime oneYearAfter = now.plus(1, ChronoUnit.YEARS);
 System.out.println(oneYearAfter); // 2023-12-23T15:44:06.356

        或者使用指定日期偏移方法完成计算:

 LocalDateTime now = LocalDateTime.now();
 System.out.println(now); // 2023-12-22T16:11:11.056

 LocalDateTime oneDayAfter = now.plusDays(1); // 给当前时间加一天 2023-12-23T16:11:11.056
 LocalDateTime oneDayAgo = now.minusDays(1); // 给当前时间减一天 2023-12-21T16:11:11.056

 LocalDateTime oneWeekAfter = now.plusWeeks(1); // 给当前时间加一周 2023-12-29T16:11:11.056
 LocalDateTime onwWeekAgo = now.minusWeeks(1); // 给当前时间减一周 2023-12-15T16:11:11.056
       
 LocalDateTime oneMonthAfter = now.plusMonths(1); // 给当前时间加一月 2024-01-22T16:11:11.056
 LocalDateTime oneMonthAgo = now.minusMonths(1); // 给当前时间减一月 2023-11-22T16:11:11.056

 LocalDateTime oneYearAfter = now.plusYears(1); // 给当前时间加一年 2024-12-22T16:11:11.056
 LocalDateTime oneYearAgo = now.minusYears(1); // 给当前时间减一年 2022-12-22T16:11:11.056

 LocalDateTime oneHourAfter = now.plusHours(1); // 给当前时间加一小时 2023-12-22T17:11:11.056
 LocalDateTime oneHourAgo = now.minusHours(1); // 给当前时间减一小时 2023-12-22T15:11:11.056

 LocalDateTime oneMinuteAfter = now.plusMinutes(1); // 给当前时间加一分钟 2023-12-22T16:12:11.056
 LocalDateTime oneMinuteAgo = now.minusMinutes(1); // 给当前时间减一分钟 2023-12-22T16:10:11.056

 LocalDateTime oneSecondAfter = now.plusSeconds(1); // 给当前时间加一秒 2023-12-22T16:11:12.056
 LocalDateTime oneSecondAgo = now.minusSeconds(1); // 给当前时间减一秒 2023-12-22T16:11:10.056

计算两个日期间隔多少年、多少月、多少天

        Java8引入了Period-计算两个日期间隔的类,使用between方法返回两个日期之间的差。

 // 计算两个日期间隔多少天、多少月、多少年
 LocalDate date1 = LocalDate.parse("2023-02-20");
 LocalDate date2 = LocalDate.parse("2023-12-30");
 Period between = Period.between(date1, date2);
 System.out.println(date1 + "与" + date2 + "相差 " + between.getYears() + "年 " + between.getMonths() + "月 " + between.getDays() + "天");
 // 2023-02-20与2023-12-30相差 0年 10月 10天

计算两个日期间隔多少天 

 long day1 = ChronoUnit.DAYS.between(date1, date2);
 System.out.println(date1 + "与" + date2 + "相差 " + day1 + "天");
 // 2023-02-20与2023-12-30相差 313天

 long day2 =date2.toEpochDay() - date1.toEpochDay();
 System.out.println(date1 + "与" + date2 + "相差 " + day2 + "天");
 // 2023-02-20与2023-12-30相差 313天

总结

Date、Calendar和LocalDateTime在Java中都是用于处理日期和时间的类,但它们之间存在一些区别。

  1. Date:这是Java 1.0提供的一个类,用于表示特定的时间点。它包含年、月、日、时、分、秒、毫秒的信息。然而,Date类在某些方面存在一些问题,例如它的线程安全性和对时区的处理方式。
  2. Calendar:这是Java 1.1提供的一个类,用于处理日期和时间。它提供了一种灵活的方式来表示和操作日期和时间。Calendar类是基于Calendar类的,它提供了一种基于特定时区的日期和时间计算方式。
  3. LocalDateTime:这是Java 8引入的一个新的日期和时间API的一部分,用于表示没有时区的日期和时间。LocalDateTime类提供了一种简单的方式来表示和操作日期和时间,并且它是线程安全的。

        总的来说,Date、Calendar和LocalDateTime的主要区别在于它们的使用场景和功能。Date主要用于表示特定的时间点,Calendar主要用于处理日期和时间的计算和操作,而LocalDateTime则主要用于表示没有时区的日期和时间。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;