這邊我就直接提供程式碼,中間其實就是無聊的 Regex 跟推算這邊有興趣,就自己再把程式碼貼給 AI 去解釋
程式碼:
public static class DateParseUtil
{
private static readonly Regex RocDateRegex =
new Regex(@"(?:國曆\s*)?(\d{2,3})[年/](\d{1,2})[月/](\d{1,2})[日號]?",
RegexOptions.Compiled);
private static readonly Regex LunarDateRegex =
// new Regex(@"農曆(\d{2,3})年(潤)?(\d{1,2})月(.+)",
new Regex(
@"農曆(\d{2,3})年(潤)?(" +
@"\d{1,2}|正|一|二|三|四|五|六|七|八|九|十|十一|十二" +
@")月(.+)",
RegexOptions.Compiled);
private static readonly TaiwanLunisolarCalendar LunarCalendar =
new TaiwanLunisolarCalendar();
// ===== Public function =====
public static bool TryParseAnyToDateTime(string input, out DateTime date)
{
date = default;
if (string.IsNullOrWhiteSpace(input))
return false;
if (input.Contains("農曆"))
return TryParseLunar(input, out date);
return TryParseRoc(input, out date);
}
// ===== 國曆 / 民國 =====
private static bool TryParseRoc(string input, out DateTime date)
{
date = default;
var match = RocDateRegex.Match(input);
if (!match.Success)
return false;
int rocYear = int.Parse(match.Groups[1].Value);
int month = int.Parse(match.Groups[2].Value);
int day = int.Parse(match.Groups[3].Value);
int year = rocYear + 1911;
try
{
date = new DateTime(year, month, day);
return true;
}
catch
{
return false;
}
}
// ===== 農曆 =====
private static bool TryParseLunar(string input, out DateTime date)
{
date = default;
var match = LunarDateRegex.Match(input);
if (!match.Success)
return false;
int lunarYear = int.Parse(match.Groups[1].Value); // 不要 +1911
bool isLeapMonth = match.Groups[2].Success;
int month = ParseChineseMonth(match.Groups[3].Value);
if (month <= 0 || month > 12)
return false;
int day = ParseChineseDay(match.Groups[4].Value);
if (day <= 0)
return false;
int leapMonth = LunarCalendar.GetLeapMonth(lunarYear);
//驗證潤的是不是這個月
// 驗證潤月合法性
if (isLeapMonth)
{
if (leapMonth == 0 || leapMonth != month + 1)
return false;
}
if (leapMonth > 0)
{
if (isLeapMonth)
{
// 潤月一定要往後推一格
month++;
}
else if (month >= leapMonth)
{
// 非潤月,但在潤月之後
month++;
}
}
try
{
date = LunarCalendar.ToDateTime(
lunarYear,
month,
day,
0, 0, 0, 0);
return true;
}
catch
{
return false;
}
}
private static readonly Dictionary ChineseDayMap =
new Dictionary
{
{ "初一", 1 }, { "初二", 2 }, { "初三", 3 }, { "初四", 4 }, { "初五", 5 },
{ "初六", 6 }, { "初七", 7 }, { "初八", 8 }, { "初九", 9 }, { "初十", 10 },
{ "十一", 11 }, { "十二", 12 }, { "十三", 13 }, { "十四", 14 }, { "十五", 15 },
{ "十六", 16 }, { "十七", 17 }, { "十八", 18 }, { "十九", 19 }, { "二十", 20 },
{ "廿一", 21 }, { "廿二", 22 }, { "廿三", 23 }, { "廿四", 24 }, { "廿五", 25 },
{ "廿六", 26 }, { "廿七", 27 }, { "廿八", 28 }, { "廿九", 29 },
{ "三十", 30 }
};
private static readonly Dictionary ChineseMonthMap =
new Dictionary
{
{ "正", 1 },
{ "一", 1 }, { "二", 2 }, { "三", 3 }, { "四", 4 },
{ "五", 5 }, { "六", 6 }, { "七", 7 }, { "八", 8 }, { "九", 9 },
{ "十", 10 }, { "十一", 11 }, { "十二", 12 }
};
private static int ParseChineseMonth(string text)
{
text = text.Trim();
if (int.TryParse(text, out var m))
return m;
if (ChineseMonthMap.TryGetValue(text, out var cm))
return cm;
return -1;
}
private static int ParseChineseDay(string text)
{
if (string.IsNullOrWhiteSpace(text))
return -1;
text = text.Replace("日", "").Trim();
// 先試中文
if (ChineseDayMap.TryGetValue(text, out var d))
return d;
// 再試數字
if (int.TryParse(text, out var n))
return n;
return -1;
}
}
呼叫方式
bool success = DateParseUtil.TryParseAnyToDateTime(input, out var dt);
測試結果透過 AI 去給我測試資料我實際跑出來後去驗證的
#
輸入字串
TryParse
DateTime
判定
01
1年1月1日
False
—
合理(規格不支援 1 位數民國)
02
10年12月31日
True
1921-12-31
正確
03
87年1月1日
True
1998-01-01
正確
04
99/12/31
True
2010-12-31
正確
05
100年1月1日
True
2011-01-01
正確
06
101/01/09
True
2012-01-09
正確
07
109年6月30日
True
2020-06-30
正確
08
110年02月28日
True
2021-02-28
正確
09
111/12/01
True
2022-12-01
正確
10
112年7月7日
True
2023-07-07
正確
11
113/03/03
True
2024-03-03
正確
12
114年11月11日
True
2025-11-11
正確
13
120/1/1
True
2031-01-01
正確
14
國曆120年12月31日
True
2031-12-31
正確
15
國曆95/6/5
True
2006-06-05
正確
16
農曆111年1月初一
True
2022-02-01
正確
17
農曆111年2月初二
True
2022-03-04
正確
18
農曆111年3月初三
True
2022-04-03
正確
19
農曆111年4月初四
True
2022-05-04
正確
20
農曆111年5月初五
True
2022-06-03
正確
21
農曆111年6月初六
True
2022-07-04
正確
22
農曆111年7月初七
True
2022-08-04
正確
23
農曆111年8月初八
True
2022-09-03
正確
24
農曆111年9月初九
True
2022-10-04
正確
25
農曆111年10月初十
True
2022-11-03
正確
26
農曆111年11月十一
True
2022-12-04
正確
27
農曆111年12月十二
True
2023-01-03
正確
28
農曆110年8月廿九
True
2021-10-05
正確
29
農曆110年12月三十
False
—
合理(該年無此日)
30
農曆109年1月十五
True
2020-02-08
正確
31
農曆108年正月初一
True
2019-02-05
正確
32
農曆108年二月初二
True
2019-03-08
正確
33
農曆108年三月初三
True
2019-04-07
正確
34
農曆108年四月初四
True
2019-05-08
正確
35
農曆108年五月初五
True
2019-06-07
正確
36
農曆108年六月初六
True
2019-07-08
正確
37
農曆108年七月初七
True
2019-08-07
正確
38
農曆108年八月初八
True
2019-09-06
正確
39
農曆108年九月初九
True
2019-10-07
正確
40
農曆108年十月初十
True
2019-11-06
正確
41
農曆112年潤2月初一
True
2023-03-22
正確(潤月)
42
農曆112年2月初一
True
2023-02-20
正確
43
農曆112年3月初一
True
2023-04-20
正確
44
農曆112年潤三月初一
False
—
合理(潤月錯誤)
45
農曆112年0月初一
False
—
合理(月非法)
46
農曆112年13月初一
False
—
合理(月超界)
47
農曆112年2月廿
False
—
合理(日不完整)
48
農曆112年2月三十一
False
—
合理(日超界)
49
農曆一一二年正月初一
False
—
合理(不支援中文年)
50
農曆112年正月初零
False
—
合理(非法日)
這邊就不過多解釋,畢竟這是方便自己之後使用的,有需要就自取吧
--
Before you read this, the article was in a superposition of human and AI. Upon observation, the wave function collapsed into a sleep-deprived developer.