Java日期時(shí)間調(diào)整的幾種方式匯總
一、Calendar類
我們現(xiàn)在已經(jīng)能夠格式化并創(chuàng)建一個(gè)日期對(duì)象了,但是我們?nèi)绾尾拍茉O(shè)置和獲取日期數(shù)據(jù)的特定部分呢,比如說小時(shí),日,或者分鐘? 我們又如何在日期的這些部分加上或者減去值呢? 答案是使用Calendar 類。
Calendar類的功能要比Date類強(qiáng)大很多,而且在實(shí)現(xiàn)方式上也比Date類要復(fù)雜一些。
Calendar類是一個(gè)抽象類,在實(shí)際使用時(shí)實(shí)現(xiàn)特定的子類的對(duì)象,創(chuàng)建對(duì)象的過程對(duì)程序員來說是透明的,只需要使用getInstance方法創(chuàng)建即可。
創(chuàng)建一個(gè)代表系統(tǒng)當(dāng)前日期的Calendar對(duì)象
Calendar c = Calendar.getInstance();//默認(rèn)是當(dāng)前日期
創(chuàng)建一個(gè)指定日期的Calendar對(duì)象
使用Calendar類代表特定的時(shí)間,需要首先創(chuàng)建一個(gè)Calendar的對(duì)象,然后再設(shè)定該對(duì)象中的年月日參數(shù)來完成。
//創(chuàng)建一個(gè)代表2009年6月12日的Calendar對(duì)象 Calendar c1 = Calendar.getInstance(); c1.set(2009, 6 - 1, 12)
Calendar類對(duì)象字段類型
Calendar類中用一下這些常量表示不同的意義,jdk內(nèi)的很多類其實(shí)都是采用的這種思想
| 常量 | 描述 |
|---|---|
| Calendar.YEAR | 年份 |
| Calendar.MONTH | 月份 |
| Calendar.DATE | 日期 |
| Calendar.DAY_OF_MONTH | 日期,和上面的字段意義完全相同 |
| Calendar.HOUR | 12小時(shí)制的小時(shí) |
| Calendar.HOUR_OF_DAY | 24小時(shí)制的小時(shí) |
| Calendar.MINUTE | 分鐘 |
| Calendar.SECOND | 秒 |
| Calendar.DAY_OF_WEEK | 星期幾 |
Calendar類對(duì)象信息的設(shè)置
Set設(shè)置
如:
Calendar c1 = Calendar.getInstance();
調(diào)用:
public final void set(int year,int month,int date)
c1.set(2009, 6 - 1, 12);//把Calendar對(duì)象c1的年月日分別設(shè)這為:2009、5、12
利用字段類型設(shè)置
如果只設(shè)定某個(gè)字段,例如日期的值,則可以使用如下set方法:
public void set(int field,int value)
把 c1對(duì)象代表的日期設(shè)置為10號(hào),其它所有的數(shù)值會(huì)被重新計(jì)算
c1.set(Calendar.DATE,10);
把c1對(duì)象代表的年份設(shè)置為2008年,其他的所有數(shù)值會(huì)被重新計(jì)算
c1.set(Calendar.YEAR,2008);
其他字段屬性set的意義以此類推
Add設(shè)置
Calendar c1 = Calendar.getInstance();
把c1對(duì)象的日期加上10,也就是c1所表的日期的10天后的日期,其它所有的數(shù)值會(huì)被重新計(jì)算
c1.add(Calendar.DATE, 10);
把c1對(duì)象的日期減去10,也就是c1所表的日期的10天前的日期,其它所有的數(shù)值會(huì)被重新計(jì)算
c1.add(Calendar.DATE, -10);
其他字段屬性的add的意義以此類推
Calendar類對(duì)象信息的獲得
Calendar c1 = Calendar.getInstance(); // 獲得年份 int year = c1.get(Calendar.YEAR); // 獲得月份 int month = c1.get(Calendar.MONTH) + 1; // 獲得日期 int date = c1.get(Calendar.DATE); // 獲得小時(shí) int hour = c1.get(Calendar.HOUR_OF_DAY); // 獲得分鐘 int minute = c1.get(Calendar.MINUTE); // 獲得秒 int second = c1.get(Calendar.SECOND); // 獲得星期幾(注意(這個(gè)與Date類是不同的):1代表星期日、2代表星期1、3代表星期二,以此類推) int day = c1.get(Calendar.DAY_OF_WEEK);
GregorianCalendar類
Calendar類實(shí)現(xiàn)了公歷日歷,GregorianCalendar是Calendar類的一個(gè)具體實(shí)現(xiàn)。
Calendar 的getInstance()方法返回一個(gè)默認(rèn)用當(dāng)前的語言環(huán)境和時(shí)區(qū)初始化的GregorianCalendar對(duì)象。GregorianCalendar定義了兩個(gè)字段:AD和BC。這些代表公歷定義的兩個(gè)時(shí)代。
下面列出GregorianCalendar對(duì)象的幾個(gè)構(gòu)造方法:
| 序號(hào) | 構(gòu)造函數(shù)和說明 |
| 1 | GregorianCalendar() 在具有默認(rèn)語言環(huán)境的默認(rèn)時(shí)區(qū)內(nèi)使用當(dāng)前時(shí)間構(gòu)造一個(gè)默認(rèn)的 GregorianCalendar。 |
| 2 | GregorianCalendar(int year, int month, int date) 在具有默認(rèn)語言環(huán)境的默認(rèn)時(shí)區(qū)內(nèi)構(gòu)造一個(gè)帶有給定日期設(shè)置的 GregorianCalendar |
| 3 | GregorianCalendar(int year, int month, int date, int hour, int minute) 為具有默認(rèn)語言環(huán)境的默認(rèn)時(shí)區(qū)構(gòu)造一個(gè)具有給定日期和時(shí)間設(shè)置的 GregorianCalendar。 |
| 4 | GregorianCalendar(int year, int month, int date, int hour, int minute, int second) 為具有默認(rèn)語言環(huán)境的默認(rèn)時(shí)區(qū)構(gòu)造一個(gè)具有給定日期和時(shí)間設(shè)置的 GregorianCalendar。 |
| 5 | GregorianCalendar(Locale aLocale) 在具有給定語言環(huán)境的默認(rèn)時(shí)區(qū)內(nèi)構(gòu)造一個(gè)基于當(dāng)前時(shí)間的 GregorianCalendar。 |
| 6 | GregorianCalendar(TimeZone zone) 在具有默認(rèn)語言環(huán)境的給定時(shí)區(qū)內(nèi)構(gòu)造一個(gè)基于當(dāng)前時(shí)間的 GregorianCalendar。 |
| 7 | GregorianCalendar(TimeZone zone, Locale aLocale) 在具有給定語言環(huán)境的給定時(shí)區(qū)內(nèi)構(gòu)造一個(gè)基于當(dāng)前時(shí)間的 GregorianCalendar。 |
這里是GregorianCalendar 類提供的一些有用的方法列表:
| 序號(hào) | 方法和說明 |
| 1 | void add(int field, int amount) 根據(jù)日歷規(guī)則,將指定的(有符號(hào)的)時(shí)間量添加到給定的日歷字段中。 |
| 2 | protected void computeFields() 轉(zhuǎn)換UTC毫秒值為時(shí)間域值 |
| 3 | protected void computeTime() 覆蓋Calendar ,轉(zhuǎn)換時(shí)間域值為UTC毫秒值 |
| 4 | boolean equals(Object obj) 比較此 GregorianCalendar 與指定的 Object。 |
| 5 | int get(int field) 獲取指定字段的時(shí)間值 |
| 6 | int getActualMaximum(int field) 返回當(dāng)前日期,給定字段的最大值 |
| 7 | int getActualMinimum(int field) 返回當(dāng)前日期,給定字段的最小值 |
| 8 | int getGreatestMinimum(int field) 返回此 GregorianCalendar 實(shí)例給定日歷字段的最高的最小值。 |
| 9 | Date getGregorianChange() 獲得格里高利歷的更改日期。 |
| 10 | int getLeastMaximum(int field) 返回此 GregorianCalendar 實(shí)例給定日歷字段的最低的最大值 |
| 11 | int getMaximum(int field) 返回此 GregorianCalendar 實(shí)例的給定日歷字段的最大值。 |
| 12 | Date getTime() 獲取日歷當(dāng)前時(shí)間。 |
| 13 | long getTimeInMillis() 獲取用長(zhǎng)整型表示的日歷的當(dāng)前時(shí)間 |
| 14 | TimeZone getTimeZone() 獲取時(shí)區(qū)。 |
| 15 | int getMinimum(int field) 返回給定字段的最小值。 |
| 16 | int hashCode() 重寫hashCode. |
| 17 | boolean isLeapYear(int year) 確定給定的年份是否為閏年。 |
| 18 | void roll(int field, boolean up) 在給定的時(shí)間字段上添加或減去(上/下)單個(gè)時(shí)間單元,不更改更大的字段。 |
| 19 | void set(int field, int value) 用給定的值設(shè)置時(shí)間字段。 |
| 20 | void set(int year, int month, int date) 設(shè)置年、月、日的值。 |
| 21 | void set(int year, int month, int date, int hour, int minute) 設(shè)置年、月、日、小時(shí)、分鐘的值。 |
| 22 | void set(int year, int month, int date, int hour, int minute, int second) 設(shè)置年、月、日、小時(shí)、分鐘、秒的值。 |
| 23 | void setGregorianChange(Date date) 設(shè)置 GregorianCalendar 的更改日期。 |
| 24 | void setTime(Date date) 用給定的日期設(shè)置Calendar的當(dāng)前時(shí)間。 |
| 25 | void setTimeInMillis(long millis) 用給定的long型毫秒數(shù)設(shè)置Calendar的當(dāng)前時(shí)間。 |
| 26 | void setTimeZone(TimeZone value) 用給定時(shí)區(qū)值設(shè)置當(dāng)前時(shí)區(qū)。 |
| 27 | String toString() 返回代表日歷的字符串。 |
實(shí)例
import java.util.*;
public class GregorianCalendarDemo {
public static void main(String args[]) {
String months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"};
int year;
// 初始化 Gregorian 日歷
// 使用當(dāng)前時(shí)間和日期
// 默認(rèn)為本地時(shí)間和時(shí)區(qū)
GregorianCalendar gcalendar = new GregorianCalendar();
// 顯示當(dāng)前時(shí)間和日期的信息
System.out.print("Date: ");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time: ");
System.out.print(gcalendar.get(Calendar.HOUR) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
// 測(cè)試當(dāng)前年份是否為閏年
if(gcalendar.isLeapYear(year)) {
System.out.println("當(dāng)前年份是閏年");
}
else {
System.out.println("當(dāng)前年份不是閏年");
}
}
}以上實(shí)例編譯運(yùn)行結(jié)果如下:
Date: Apr 22 2009
Time: 11:25:27
當(dāng)前年份不是閏年
二、周期方法
周期是以年,月和日為單位的時(shí)間跨度。
支持負(fù)周期。
持續(xù)時(shí)間也是以秒和納秒為單位測(cè)量的時(shí)間跨度。
持續(xù)時(shí)間表示機(jī)器的精確納秒數(shù)。一個(gè)時(shí)期更適合人類。
1天,2個(gè)月,3天,4個(gè)月和5天都是周期的實(shí)例。2個(gè)月期間可能意味著不同的天數(shù),具體取決于不同的月份。
我們可以使用以下方法創(chuàng)建 Period 。
static Period of(int years,int months, int days) static Period ofDays(int days) static Period ofMonths(int months) static Period ofWeeks(int weeks) static Period ofYears(int years)
以下代碼顯示了如何創(chuàng)建Period。
import java.time.Period;
public class Main {
public static void main(String[] args) {
Period p1 = Period.of(2, 3, 5); // 2 years, 3 months, and 5 days
Period p2 = Period.ofDays(2); // 2 days
Period p3 = Period.ofMonths(-3); // -3 months
Period p4 = Period.ofWeeks(3); // 3 weeks
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
System.out.println(p4);
}
}上面的代碼生成以下結(jié)果。

例2
Period支持加法,減法,乘法和求反運(yùn)算。
除法運(yùn)算執(zhí)行整數(shù)除法,例如,除以3除以7為2。
以下代碼顯示如何使用周期上的操作。
import java.time.Period;
public class Main {
public static void main(String[] args) {
Period p1 = Period.ofDays(15);
System.out.println(p1);
Period p2 = p1.plusDays(12);
System.out.println(p2);
Period p3 = p1.minusDays(12);
System.out.println(p3);
Period p4 = p1.negated();
System.out.println(p4);
Period p5 = p1.multipliedBy(3);
System.out.println(p5);
}
}上面的代碼生成以下結(jié)果。

例3
Period plus()
向另一個(gè)周期添加一個(gè)周期。
Period minus()
從另一個(gè)周期中減去一個(gè)周期。
周期normalized()方法標(biāo)準(zhǔn)化年和月。該方法確保月份值保持在0到11之間。“2年零16個(gè)月"被標(biāo)準(zhǔn)化為“3年零4個(gè)月"。
import java.time.Period;
public class Main {
public static void main(String[] args) {
Period p1 = Period.of(2, 3, 5);
Period p2 = Period.of(1, 15, 28);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1.minus(p2));
System.out.println(p1.plus(p2));
System.out.println(p1.plus(p2).normalized());
}
}上面的代碼生成以下結(jié)果。

Period Between
Date-Time API提供了計(jì)算兩個(gè)日期和時(shí)間之間的已用時(shí)間的方法。
我們可以在ChronoUnit枚舉中的一個(gè)常量上使用 between()方法。
ChronoUnit枚舉between()方法需要兩個(gè)datetime對(duì)象并返回一個(gè)long。 如果第二個(gè)參數(shù)出現(xiàn)在第一個(gè)參數(shù)之前,它返回一個(gè)負(fù)數(shù)。
返回金額是兩個(gè)日期和時(shí)間之間的完整單位數(shù)。 例如,在06:00和09:30之間調(diào)用HOURS.between(),返回值為3,而不是3.5。 而MINUTES.在06:00至09:30之間返回210。
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2014, Month.JANUARY, 7);
LocalDate ld2 = LocalDate.of(2014, Month.MAY, 21);
long days = ChronoUnit.DAYS.between(ld1, ld2);
System.out.println(days);
LocalTime lt1 = LocalTime.of(6, 0);
LocalTime lt2 = LocalTime.of(9, 30);
long hours = ChronoUnit.HOURS.between(lt1, lt2);
System.out.println(hours);
long minutes = ChronoUnit.MINUTES.between(lt1, lt2);
System.out.println(minutes);
}
}上面的代碼生成以下結(jié)果。

Period Util
Date-Time API提供了計(jì)算兩個(gè)日期和時(shí)間之間的已用時(shí)間的方法。
我們可以對(duì)一個(gè)日期時(shí)間相關(guān)類使用 until(end_date_or_time,time_unit)方法,例如LocalDate,LocalTime,LocalDateTime,ZonedDateTime等。
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2014, Month.JANUARY, 7);
LocalDate ld2 = LocalDate.of(2014, Month.MAY, 18);
LocalTime lt1 = LocalTime.of(7, 0);
LocalTime lt2 = LocalTime.of(9, 30);
long days = ld1.until(ld2, ChronoUnit.DAYS);
System.out.println(days);
long hours = lt1.until(lt2, ChronoUnit.HOURS);
System.out.println(hours);
long minutes = lt1.until(lt2, ChronoUnit.MINUTES);
System.out.println(minutes);
}
}上面的代碼生成以下結(jié)果。

三、Java 日期時(shí)間調(diào)整器
我們可能要將日期和時(shí)間調(diào)整為該月的第一個(gè)星期一或下一個(gè)星期二。
我們可以使用 TemporalAdjuster 界面來調(diào)整日期和時(shí)間。接口有一個(gè)方法, adjustInto(),它接受一個(gè)時(shí)間并返回一個(gè)時(shí)間。
TemporalAdjusters 類包含返回不同類型的預(yù)定義日期調(diào)整器的靜態(tài)方法。
以下代碼顯示了如何計(jì)算2014年1月1日之后的第一個(gè)星期一:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2014, Month.JANUARY, 1);
LocalDate ld2 = ld1.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println(ld1);
System.out.println(ld2);
}
}上面的代碼生成以下結(jié)果。

TemporalAdjusters
TemporalAdjusters定義了一些可用于調(diào)整日期的有用方法。
- next(DayOfWeek dayOfWeek)
- nextOrSame(DayOfWeek dayOfWeek)
- previous(DayOfWeek dayOfWeek)
- previousOrSame(DayOfWeek dayOfWeek)
- firstInMonth(DayOfWeek dayOfWeek)
- lastInMonth(DayOfWeek dayOfWeek)
- dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)
- firstDayOfMonth()
- lastDayOfMonth()
- firstDayOfYear()
- lastDayOfYear()
- firstDayOfNextMonth()
- firstDayOfNextYear()
- ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster)
以下代碼顯示了如何使用 dayOfWeekInMonth 。
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2014, Month.MAY, 21);
System.out.println(ld1);
LocalDate ld2 = ld1.with(TemporalAdjusters.dayOfWeekInMonth(5, DayOfWeek.SUNDAY));
System.out.println(ld2);
}
}上面的代碼生成以下結(jié)果。

自定義調(diào)整
您可以使用ofDateAdjuster()方法為L(zhǎng)ocalDate創(chuàng)建自己的日期調(diào)整器。
以下代碼創(chuàng)建日期調(diào)整程序。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
// Create an adjuster that retruns a date after 3 months and 2 days
TemporalAdjuster adjuster = TemporalAdjusters
.ofDateAdjuster((LocalDate date) -> date.plusMonths(3).plusDays(2));
LocalDate today = LocalDate.now();
LocalDate dayAfter3Mon2Day = today.with(adjuster);
System.out.println("Today: " + today);
System.out.println("After 3 months and 2 days: " + dayAfter3Mon2Day);
}
}上面的代碼生成以下結(jié)果:

到此這篇關(guān)于Java日期時(shí)間調(diào)整的幾種方式的文章就介紹到這了,更多相關(guān)Java日期時(shí)間調(diào)整內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java為移動(dòng)端寫接口開發(fā)實(shí)例
本篇文章主要介紹了java如何為移動(dòng)端寫接口,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
SpringBoot中使用configtree讀取樹形文件目錄中的配置詳解
這篇文章主要介紹了SpringBoot中使用configtree讀取樹形文件目錄中的配置詳解,configtree通過spring.config.import?+?configtree:前綴的方式,加載以文件名為key、文件內(nèi)容為value的配置屬性,需要的朋友可以參考下2023-12-12
Mybatis的插件運(yùn)行原理及如何編寫一個(gè)插件
這篇文章主要介紹了Mybatis的插件運(yùn)行原理及如何編寫一個(gè)插件 ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
基于SpringAop中JoinPoint對(duì)象的使用說明
這篇文章主要介紹了基于SpringAop中JoinPoint對(duì)象的使用說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java8中創(chuàng)建Stream流的幾種常見方式
在Java 8中,??Stream?? API 是一種新的處理數(shù)據(jù)的方式,它允許以聲明式的方式來處理數(shù)據(jù)集合,本文將詳細(xì)介紹在Java 8中創(chuàng)建 ??Stream?? 流的幾種常見方式,大家可以根據(jù)需要進(jìn)行選擇2025-05-05
java實(shí)現(xiàn)寫入并保存txt文件的代碼詳解
在本篇文章里小編給大家整理了關(guān)于java實(shí)現(xiàn)寫入并保存txt文件的代碼實(shí)例內(nèi)容,需要的朋友們可以參考學(xué)習(xí)下。2020-02-02
Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決
這篇文章主要介紹了Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04

