首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

帶閏年判斷的日期正則表達式:1800-3999 年完整匹配方案

     編輯:關於C語言

需求背景

驗證 YYYY-MM-DD 格式日期,年份範圍 1800-3999,需精確校驗閏年規則:

  • 普通年:能被 4 整除但不能被 100 整除 → 閏年。
  • 世紀年:能被 400 整除 → 閏年 (如 2000);否則平年 (如 1900)。

正則表達式構建策略

將年份分為閏年與平年兩大類,分別構造年份正則,再組合月份/日期部分。

核心正則片段 (Java/JS 風格)

1. 閏年年份


// 非世紀閏年:尾數 04,08,12...96 (不含 00)
String leap1 = "((1[8-9]|[2-3]\\d)(0[48]|[2468][048]|[13579][26]))";
// 世紀閏年:2000,2400,2800,3200,3600
String leap2 = "((20|24|28|32|36)00)";
// 合併閏年
String leapYear = "(" + leap1 + "|" + leap2 + ")";

2. 平年年份


// 非世紀平年:尾數 01-99 除去閏年尾數
String noleap1 = "((1[8-9]|[2-3]\\d)(0[1235679]|[13579][01345789]|[2468][1235679]))";
// 世紀平年:1800,1900,2100...3900 (除 2000,2400...)
String noleap2 = "((18|19|21|22|23|25|26|27|29|30|31|33|34|35|37|38|39)00)";
// 合併平年
String noleapYear = "(" + noleap1 + "|" + noleap2 + ")";

3. 月份與日期 (通用部分)


// 31天月份:01,03,05,07,08,10,12
String month31 = "(0[13578]|1[02])-([0-2]\\d|3[01])";
// 30天月份:04,06,09,11
String month30 = "(0[469]|11)-([0-2]\\d|30)";
// 2月平年:01-28
String febNormal = "02-([0-1]\\d|2[0-8])";
// 2月閏年:01-29
String febLeap = "02-([0-1]\\d|2[0-9])";

4. 完整組合


String dateRegex = 
    "^(" + leapYear + ")-(" + febLeap + "|" + month30 + "|" + month31 + ")" +
  "|^(" + noleapYear + ")-(" + febNormal + "|" + month30 + "|" + month31 + ")" +
"$";

優化版:單一正則 (PCRE/Java/JS 通用)


^(
  # 閏年
  (
    (1[8-9]|[2-3]\d)(0[48]|[2468][048]|[13579][26])   # 非世紀閏年
  | (20|24|28|32|36)00                                 # 世紀閏年
  )
  -
  (
    02-(0[1-9]|1\d|2[0-9])                             # 閏年2月 01-29
  | (0[13578]|1[02])-(0[1-9]|[12]\d|3[01])             # 31天月
  | (0[469]|11)-(0[1-9]|[12]\d|30)                     # 30天月
  )
|
  # 平年
  (
    (1[8-9]|[2-3]\d)(0[1235679]|[13579][01345789]|[2468][1235679]) # 非世紀平年
  | (18|19|21|22|23|25|26|27|29|30|31|33|34|35|37|38|39)00       # 世紀平年
  )
  -
  (
    02-(0[1-9]|1\d|2[0-8])                             # 平年2月 01-28
  | (0[13578]|1[02])-(0[1-9]|[12]\d|3[01])             # 31天月
  | (0[469]|11)-(0[1-9]|[12]\d|30)                     # 30天月
  )
)$

各語言使用示例

Java


Pattern pattern = Pattern.compile(DATE_REGEX);
Matcher m = pattern.matcher("2000-02-29");
boolean valid = m.matches(); // true

JavaScript


const regex = new RegExp(DATE_REGEX);
regex.test("1900-02-29"); // false

Python


import re
re.fullmatch(DATE_REGEX, "2024-02-29") # 匹配

性能與替代方案

  • 正則雖完整但難維護、回溯風險大。
  • 生產環境建議:正則校驗格式 + 代碼邏輯校驗日期合法性(如 LocalDate.parse、datetime.strptime)。
  • 若必須用正則,可預編譯並限制輸入長度。

總結

本文提供了1800-3999 年嚴格遵循格里曆閏年規則的日期正則表達式,分為模塊化構建版與單一優化版,適用於 Java、JS、Python、PCRE 等引擎。實際項目中推薦「正則管格式,代碼管邏輯」的分層校驗策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved