Java日期格式化如何避免YYYY引發(fā)的時間異常
在編程中,日期格式化是一個常見的任務。使用不同的格式化選項可能會導致一些意外的結果。最近遇到一個問題,就是使用YYYY格式化選項會導致時間異常。
public static void main(String[] args) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); String time = "2023-12-31 23:59:59"; System.out.printf("yyyy-MM-dd HH:mm:ss: %s\n",sdf.format(sdf.parse(time))); System.out.printf("YYYY-MM-dd HH:mm:ss: %s\n",sdf2.format(sdf2.parse(time))); System.out.println("======================================"); String time2 = "2023-11-31 23:59:59"; //11月沒有31號 System.out.printf("yyyy-MM-dd HH:mm:ss: %s\n",sdf.format(sdf.parse(time2))); System.out.printf("YYYY-MM-dd HH:mm:ss: %s\n",sdf2.format(sdf2.parse(time2))); System.out.println("======================================"); String time3 = "2023-10-31 23:59:59"; System.out.printf("yyyy-MM-dd HH:mm:ss: %s\n",sdf.format(sdf.parse(time3))); System.out.printf("YYYY-MM-dd HH:mm:ss: %s\n",sdf2.format(sdf2.parse(time3))); }
輸出結果
yyyy-MM-dd HH:mm:ss: 2023-12-31 23:59:59
YYYY-MM-dd HH:mm:ss: 2023-01-01 23:59:59
======================================
yyyy-MM-dd HH:mm:ss: 2023-12-01 23:59:59
YYYY-MM-dd HH:mm:ss: 2023-01-01 23:59:59
======================================
yyyy-MM-dd HH:mm:ss: 2023-10-31 23:59:59
YYYY-MM-dd HH:mm:ss: 2023-01-01 23:59:59
網(wǎng)上查閱說大寫的YYYY表示一個基于周的年份,它是根據(jù)周計算的年份,而不是基于日歷的年份。通常情況下,兩者的結果是相同的,但在跨年的第一周或最后一周可能會有差異。但這里發(fā)現(xiàn)無論怎么調(diào)整時間,YYYY-MM-dd HH:mm:ss格式化后一直是2023-01-01 23:59:59,不僅僅是在跨年的時候出現(xiàn)問題,具體原因尚不清楚
如何避免
定義通用的格式類,所有使用日期格式的地方都引用這個類,這個類中就定義好yyyy-MM-dd格式即可,這樣就不會出現(xiàn)有人手誤給大家埋雷了。
public class LocalDateUtils { /** * 顯示年月日時分秒,例如 2023-10-31 09:51:53. */ public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; /** * 僅顯示年月日,例如 2023-10-31. */ public static final String DATE_PATTERN = "yyyy-MM-dd"; private static final String YEAR = "year"; private static final String MONTH = "month"; private static final String WEEK = "week"; private static final String DAY = "day"; /** * 將日期轉(zhuǎn)換為字符串,格式為:yyyy-MM-dd HH:mm:ss */ public static String getLocalDateTimeStr(LocalDateTime localDateTime) { return format(localDateTime, DATETIME_PATTERN); } /** * 將日期轉(zhuǎn)換為字符串,格式為:yyyy-MM-dd */ public static String getLocalDateStr(LocalDateTime localDateTime) { return format(localDateTime, DATE_PATTERN); } /** * 將字符串轉(zhuǎn)換為日期,格式為:yyyy-MM-dd HH:mm:ss */ public static LocalDateTime parseLocalDateTime(String localDateTimeStr) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_PATTERN); return LocalDateTime.parse(localDateTimeStr, dateTimeFormatter); } /** * 將字符串轉(zhuǎn)換為日期,格式為:yyyy-MM-dd */ public static LocalDate parseLocalDate(String localDateStr) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN); return LocalDate.parse(localDateStr, dateTimeFormatter); } /** * 將字符串轉(zhuǎn)日期成Long類型的時間戳 */ public static Long convertLocalDateTimeToLong(String time) { LocalDateTime parse = parse(time, DATETIME_PATTERN); return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } /** * 將字符串轉(zhuǎn)日期成Long類型的時間戳 */ public static Long convertLocalDateToLong(String time) { LocalDateTime parse = parse(time, DATE_PATTERN); return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } public static LocalDateTime parse(String time, String pattern) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); return LocalDateTime.parse(time, dateTimeFormatter); } /** * 將Long類型的時間戳轉(zhuǎn)換成String 類型的時間格式 */ public static String getLocalDateTimeStr(Long time) { return format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()), DATETIME_PATTERN); } /** * 將Long類型的時間戳轉(zhuǎn)換成String 類型的時間格式,時間格式為:yyyy-MM-dd */ public static String getLocalDateStr(Long time) { return format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()), DATE_PATTERN); } /** * 獲取日期時間字符串 */ public static String format(TemporalAccessor temporal, String pattern) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); return dateTimeFormatter.format(temporal); } /** * 取本月第一天 */ public static LocalDate firstDayOfThisMonth() { LocalDate today = LocalDate.now(); return today.with(TemporalAdjusters.firstDayOfMonth()); } /** * 取本月第N天 */ public static LocalDate dayOfThisMonth(int n) { LocalDate today = LocalDate.now(); return today.withDayOfMonth(n); } /** * 取本月最后一天 */ public static LocalDate lastDayOfThisMonth() { LocalDate today = LocalDate.now(); return today.with(TemporalAdjusters.lastDayOfMonth()); } /** * 獲取指定日期時間加上指定數(shù)量日期時間單位之后的日期時間. */ public static LocalDateTime plus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) { return localDateTime.plus(num, chronoUnit); } /** * 獲取指定日期時間減去指定數(shù)量日期時間單位之后的日期時間. */ public static LocalDateTime minus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) { return localDateTime.minus(num, chronoUnit); } /** * 根據(jù)ChronoUnit計算兩個日期時間之間相隔日期時間 */ public static long getChronoUnitBetween(LocalDateTime start, LocalDateTime end, ChronoUnit chronoUnit) { return Math.abs(start.until(end, chronoUnit)); } /** * 根據(jù)ChronoUnit計算兩個日期之間相隔年數(shù)或月數(shù)或天數(shù) */ public static long getChronoUnitBetween(LocalDate start, LocalDate end, ChronoUnit chronoUnit) { return Math.abs(start.until(end, chronoUnit)); } /** * 切割日期。按照周期切割成小段日期段。例如: <br> * * @param startDate 開始日期(yyyy-MM-dd) * @param endDate 結束日期(yyyy-MM-dd) * @param period 周期(天,周,月,年) * @return 切割之后的日期集合 * <li>startDate="2023-10-27",endDate="2023-10-31",period="day"</li> * <li>結果為:[2023-10-27, 2023-10-28, 2023-10-29, 2023-10-03,2023-10-31]</li><br> * <li>startDate="2023-10-27",endDate="2023-10-31",period="week"</li> * <li>結果為:[2023-10-27,2023-10-31]</li><br> * <li>startDate="2023-10-27",endDate="2023-10-31",period="month"</li> * <li>結果為:[2023-10-27,2023-10-31]</li><br> * <li>startDate="2023-10-27",endDate="2023-10-31",period="year"</li> * <li>結果為:[2023-10-27,2023-10-31]</li><br> */ public static List<String> listDateStrs(String startDate, String endDate, String period) { List<String> result = new ArrayList<>(); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN); LocalDate end = LocalDate.parse(endDate, dateTimeFormatter); LocalDate start = LocalDate.parse(startDate, dateTimeFormatter); LocalDate tmp = start; switch (period) { case DAY: while (start.isBefore(end) || start.isEqual(end)) { result.add(start.toString()); start = start.plusDays(1); } break; case WEEK: while (tmp.isBefore(end) || tmp.isEqual(end)) { if (tmp.plusDays(6).isAfter(end)) { result.add(tmp.toString() + "," + end); } else { result.add(tmp.toString() + "," + tmp.plusDays(6)); } tmp = tmp.plusDays(7); } break; case MONTH: while (tmp.isBefore(end) || tmp.isEqual(end)) { LocalDate lastDayOfMonth = tmp.with(TemporalAdjusters.lastDayOfMonth()); if (lastDayOfMonth.isAfter(end)) { result.add(tmp.toString() + "," + end); } else { result.add(tmp.toString() + "," + lastDayOfMonth); } tmp = lastDayOfMonth.plusDays(1); } break; case YEAR: while (tmp.isBefore(end) || tmp.isEqual(end)) { LocalDate lastDayOfYear = tmp.with(TemporalAdjusters.lastDayOfYear()); if (lastDayOfYear.isAfter(end)) { result.add(tmp.toString() + "," + end); } else { result.add(tmp.toString() + "," + lastDayOfYear); } tmp = lastDayOfYear.plusDays(1); } break; default: break; } return result; } }
以上就是Java日期格式化如何避免YYYY引發(fā)的時間異常的詳細內(nèi)容,更多關于Java日期格式化的資料請關注腳本之家其它相關文章!
相關文章
Spring AOP使用@Aspect注解 面向切面實現(xiàn)日志橫切的操作
這篇文章主要介紹了Spring AOP使用@Aspect注解 面向切面實現(xiàn)日志橫切的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java注解如何基于Redission實現(xiàn)分布式鎖
這篇文章主要介紹了Java注解如何基于Redission實現(xiàn)分布式鎖,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01Springboot集成Quartz實現(xiàn)定時任務代碼實例
這篇文章主要介紹了Springboot集成Quartz實現(xiàn)定時任務代碼實例,任務是有可能并發(fā)執(zhí)行的,若Scheduler直接使用Job,就會存在對同一個Job實例并發(fā)訪問的問題,而JobDetail?&?Job方式,Scheduler都會根據(jù)JobDetail創(chuàng)建一個新的Job實例,這樣就可以規(guī)避并發(fā)訪問問題2023-09-09java基于Des對稱加密算法實現(xiàn)的加密與解密功能詳解
這篇文章主要介紹了java基于Des對稱加密算法實現(xiàn)的加密與解密功能,結合實例形式詳細分析了Des加密算法的功能、原理、使用方法與相關注意事項,需要的朋友可以參考下2017-01-01Java開發(fā)環(huán)境配置教程(win7 64bit)
這篇文章主要為大家詳細介紹了win7 64bit下Java開發(fā)環(huán)境的配置教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08SpringBoot3.4.0無法找到StringRedisTemplate?bean的問題Consider?def
本文主要介紹了SpringBoot3.4.0無法找到StringRedisTemplate?bean的問題Consider?defining?a?bean?of?type?‘org.springframework,具有一定的參考價值,感興趣的可以了解一下2025-03-03