在日常開發中,無論是數據統計、活動倒計時、定時任務等都需要進行時間操作,其中一項常見的操作是加減日期,例如:將今天的日期往前或往後推幾天、幾個月、幾年,以及具體到某一天、某一時刻等。
一、Java 時間類
Java提供了一個處理日期和時間的類——Date,儘管它在Java SE 8中已經可以棄用使用,但是對於基礎知識的學習,介紹起來還是有必要的。
public class Date { /** * 分配給 Date 對象的唯一標識符。 */ private transient long fastTime; //...其他成員變量和方法 }
由上述代碼分析可知,Date 類利用一個「long型」的變量存儲日期時間信息,毫秒級別的時間戳可以完美地用long類型來表示,但是該類並沒有提供很好的時間計算方法。
二、Java Calendar 類
Java中的Calendar類是一個抽象類,提供了豐富的日期時間計算和轉換接口,由此也可以得出另一條結論:Java 預算日期操作最好使用 Calendar 類。
1. Calendar 類方法
Calendar 類提供的方法如下:
- 根據日期設置年、月、日等時間信息。
- 提供了獲取日期時間各部分信息的接口,如獲取年、月、日、小時、分鐘、秒等。
- 提供了時間增減計算接口,如 add、roll 等方法。
- Calendar 類提供了格式化日期的接口,例如,getDisplayName等。
- Calendar 類提供了時區的操作接口。
其中 add 和 roll 方法都是時間增量計算方法,兩者的區別在於對於跨年的加減日期處理方式不同。
2. Calendar 類代碼示例
/** * 獲取某一天的開始時間 * * @param calendar 時間對象 * @return 當天起始時間 */ public static Date getStartTimeOfDay(Calendar calendar) { Date date = calendar.getTime(); try { calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } catch (Exception e) { log.error("", e); } return null; }
上述代碼是獲取某一天的開始時間方法的實現,利用 Calendar 類的 getTime() 方法獲取當前時間,在設置成員變量中各部分時間為 0,即可得到當天開始時間。
三、時間計算區間工具類
為方便日後使用,我們通常會封裝一個工具類,來計算時間的加減和計算區間等。
1. 時間計算工具類代碼示例
/** * 時間計算工具類 ** 包含獲取某一時間之前或之後的時間,以及計算時間區間等方法。 */public class DateUtil { /** * 指定時間加減年份 * * @param date 日期 * @param yearAmount 年數,正數代表往後推,負數代表往前推 * @return 計算完後的日期 */ public static Date addYear(Date date, int yearAmount) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.YEAR, yearAmount); return c.getTime(); } /** * 指定時間加減月份 * * @param date 日期 * @param monthAmount 月數,正數代表往後推,負數代表往前推 * @return 計算完後的日期 */ public static Date addMonth(Date date, int monthAmount) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.MONTH, monthAmount); return c.getTime(); } /** * 指定時間加減天數 * * @param date 日期 * @param dayAmount 日數,正數代表往後推,負數代表往前推 * @return 計算完後的日期 */ public static Date addDay(Date date, int dayAmount) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.DAY_OF_MONTH, dayAmount); return c.getTime(); } /** * 指定時間加減小時數 * * @param date 日期 * @param hourOfdayAmount 小時數,正數代表往後推,負數代表往前推 * @return 計算完後的日期 */ public static Date addHourOfDay(Date date, int hourOfdayAmount) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.HOUR_OF_DAY, hourOfdayAmount); return c.getTime(); } /** * 指定時間加減分鐘數 * * @param date 日期 * @param minuteAmount 分鐘數,正數代表往後推,負數代表往前推 * @return 計算完後的日期 */ public static Date addMinute(Date date, int minuteAmount) { Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.MINUTE, minuteAmount); return c.getTime(); }
上述代碼通過 Calendar 類提供的 add 方法,對時間的年、月、日、時、分等信息進行加減,從而實現時間操作的目的。
2. 時間區間計算代碼示例
/** * 時間區間計算工具類 ** 如果 startTime 為null,endTime 不為null,則返回endTime到當前的區間列表。 * 如果 endTime 為null,startTime 不為null,則返回startTime到當前的區間列表。 * 如果 startTime 和 endTime 都為null,則返回全年或全月或全日的區間列表。 * * @param startTime 開始日期 * @param endTime 結束日期 * @return 時間區間列表 */public static List getTimeInterval(String startTime, String endTime) throws Exception { if ((startTime == null || startTime.trim().equals("")) && (endTime == null || endTime.trim().equals(""))) { throw new Exception("開始時間和結束時間不能同時為空!"); } List result = new ArrayList(); SimpleDateFormat sdf = null; DateTimeFormatter formatter = null; String datePattern = ""; LocalDateTime nowLdt = LocalDateTime.now(); LocalDateTime startLdt = null; LocalDateTime endLdt = null; Integer year = null; Integer month = null; if (!StringUtils.isEmpty(startTime)) { datePattern = getPattern(startTime); if (datePattern == null || datePattern.equals("")) { throw new Exception("開始時間格式錯誤!(yyyy-MM-dd或yyyy-MM-dd HH:mm:ss)"); } //解決java.time.DateTimeParseException異常問題 formatter = DateTimeFormatter.ofPattern(datePattern); startLdt = LocalDateTime.parse(startTime, formatter); year = startLdt.getYear(); month = startLdt.getMonth().getValue(); } if (!StringUtils.isEmpty(endTime)) { datePattern = getPattern(endTime); if (datePattern == null || datePattern.equals("")) { throw new Exception("結束時間格式錯誤!(yyyy-MM-dd或yyyy-MM-dd HH:mm:ss)"); } //解決java.time.DateTimeParseException異常問題 formatter = DateTimeFormatter.ofPattern(datePattern); endLdt = LocalDateTime.parse(endTime, formatter); year = endLdt.getYear(); month = endLdt.getMonth().getValue(); } int startYear = year == null ? nowLdt.getYear() : year; int endYear = year == null ? nowLdt.getYear() : year; int startMon = month == null ? nowLdt.getMonthValue() : month; int endMon = month == null ? nowLdt.getMonthValue() : month; if (startLdt != null) { startYear = startLdt.getYear(); startMon = startLdt.getMonthValue(); } if (endLdt != null) { endYear = endLdt.getYear(); endMon = endLdt.getMonthValue(); } if (startLdt != null && endLdt != null && startLdt.isBefore(nowLdt) && endLdt.isAfter(nowLdt)) { startYear = nowLdt.getYear(); startMon = nowLdt.getMonthValue(); } for (int yearIndex = startYear; yearIndex endMon) || (startYear nowLdt.getMonthValue())) { break; } int startMonIndex = 1; int endMonIndex = 12; if (yearIndex == startYear && yearIndex == endYear) { startMonIndex = startMon; endMonIndex = endMon; } else if (yearIndex == startYear) { startMonIndex = startMon; } else if (yearIndex == endYear) { endMonIndex = endMon; } for (int monIndex = startMonIndex; monIndex <= endMonIndex; monIndex++) { LocalDate localDate = LocalDate.of(yearIndex, monIndex, 1); int maxDaysOfMonth = localDate.lengthOfMonth(); String startTimeStr = ""; String endTimeStr = ""; if (startLdt != null && startLdt.getYear() == yearIndex && startLdt.getMonthValue() == monIndex) { startTimeStr = startTime; } else { startTimeStr = yearIndex + "-" + formatNumber(monIndex) + "-01 00:00:00"; } if (endLdt != null && endLdt.getYear() == yearIndex && endLdt.getMonthValue() == monIndex) { endTimeStr = endTime; } else { endTimeStr = yearIndex + "-" + formatNumber(monIndex) + "-" + maxDaysOfMonth + " 23:59:59"; } result.add(startTimeStr + "|" + endTimeStr); } } return result;}private static String getPattern(String date) { if (date.contains("-")) { return date.contains(":") ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd"; } else if (date.contains("/")) { return date.contains(":") ? "yyyy/MM/dd HH:mm:ss" : "yyyy/MM/dd"; } return "";}private static String formatNumber(int value) { return value < 10 ? "0" + value : String.valueOf(value);}
上述代碼中演示了時間區間計算的示例。根據輸入的開始時間和結束時間,計算出時間區間列表。例如,在輸入 2019-06-01 和 2019-07-01 時,輸出「2019-06-01 00:00:00|2019-06-30 23:59:59」、「2019-07-01 00:00:00|2019-07-01 23:59:59」兩個時間區間。
四、總結
時間計算在日常開發中是經常遇到的任務,Java 中提供了多種計算日期的方法和類。其中,我們建議使用 Calendar 類,實現增減日期,包含了較為豐富的接口。此外,為方便使用和復用,我們可以封裝一個時間計算工具類,增加代碼復用性。
原創文章,作者:FKBVW,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/334045.html