前言 回歸分析就是用於預測輸入變數(自變數)和輸出變數(因變數)之間的關係,特別當輸入的值發生變化時,輸出變數值也發生改變!回歸簡單來說就是對數據進行擬合。線性回歸就是通過線性的函數對數據進行擬合。機器學習並不能實現預言,只能實現簡單的預測。我們這次對房價關於其他因素的關係。 波士頓房價預測 下載相 ...
一、介紹
正則表達式可用於匹配各種模式,本文將用java中的正則來檢測給定字元串是否飲包含有效日期
二、日期格式概述
先對西曆中一個有效日期做一個定義,日期格式我們一般定義為yyyy-MM-dd。考慮範圍大小年、閏年等情況,先說閏年。
普通閏年:西曆年份是4的倍數,且不是100的倍數的,為閏年(如2004年、2020年等就是閏年)。
世紀閏年:西曆年份是整百數的,必須是400的倍數才是閏年(如1900年不是閏年,2000年是閏年)。
有效日期舉例:
- 2017-12-31
- 2020-02-29
- 2400-02-29
無效日期舉例
- 2017/12/31: 分割符不正確
- 2018-1-1: 沒有前導0
- 2018-04-31: 天數不正確
- 2100-02-29: 平年2月只有28天
三、實現
我們要用正則匹配日期,首先先定義一個介面DateMatcher,只提供一個匹配方法
public interface DateMatcher {
boolean matches(String date);
}
下麵逐步介紹實現,構建一個完整解決方案
3.1 匹配數字
創建一個簡單的正則來對字元串進行格式約束:
public class FormattedDateMatcher implements DateMatcher {
private static final Pattern DATE_PATTERN =
Pattern.compile("^\\d{2}-\\d{4}-\\d{2}$");
@Override
public boolean matches(String date) {
return DATE_PATTERN.matcher(date).matches();
}
}
這裡我們指定了一個有效日期必須由三組中劃線分割的整數組成,第一組由4個整數,其餘兩組各有兩個整數。
舉例:
匹配的日期: 2017-12-31, 2018-01-31, 0000-00-00, 1029-00-72
不匹配的日期:2018-01, 2018-01-XX, 2020/02/09
3.2 匹配日期的範圍
現在我們成功匹配了一般日期格式,現在我們做進一步約束,我們將年份限定在1900-2999,月份和日期也做同樣的約束
^((19|2[0-9])[0-9]{2})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$
這裡我們對三組整數範圍做了約束
- ((19|2[0-9])[0-9]{2}),通過匹配一個以19開頭或2X開頭後跟幾個任意數字的數字來覆蓋年份的範圍
- (0[1-9]|1[012]),匹配01-12範圍內的月份
- (0[1-9]|[12][0-9]|3[01]),匹配01-31範圍內的天數
匹配的日期:1900-01-01,2205-02-31,2999-12-31
不匹配的日期:1989-12-31,2018-05-35,2018-13-05,3000-01-01,2018-01-XX
3.3 匹配2月29
為了匹配2月29,首先要判斷閏年,把1900-2099之間的閏年匹配出來。如果一個數的後2位能被4整除則原數也能被4整除;如果後兩位是00,這個數能被100整除
^((2000|2400|2800|(19|2[0-9])(0[48]|[2468][048]|[13579][26]))-02-29)$
這個正則由以下部分組成
- 2000|2400|2800 匹配一組閏年,在1900-2999的範圍內,匹配能被400整除的
- 19|20-9 匹配能被4整除不能被100整除的
- 02-29 匹配2月29
舉例
匹配的日期:2020-02-29,2024-02-29,2400-02-29
不匹配的日期:2019-02-29,2100-02-29,3200-02-29,2020/02/29
3.4 匹配2月28
2月29是閏年,我們還要匹配平年的2月28
^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$
舉例:
匹配的日期: 2018-02-01, 2019-02-13, 2020-02-25
不匹配的日期: 2000-02-30, 2400-02-62, 2018/02/28
3.5. Matching 31-Day Months
3.5 匹配31天的月份
1、3、5、7、8、10、12月份每月31天
^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$
舉例:
匹配的日期: 2018-01-31, 2021-07-31, 2022-08-31
不匹配的日期: 2018-01-32, 2019-03-64, 2018/01/31
3.6 匹配30天的月份
4、6、9、11每月30天
^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$
舉例:
匹配的月份: 2018-04-30, 2019-06-30, 2020-09-30
不匹配的月份: 2018-04-31, 2019-06-31, 2018/04/30
3.7 彙總的日期匹配器
現在我們將上面的所有模式合併成一個匹配器滿足所有的日期約束
class GregorianDateMatcher implements DateMatcher {
private static Pattern DATE_PATTERN = Pattern.compile(
"^((2000|2400|2800|(19|2[0-9])(0[48]|[2468][048]|[13579][26]))-02-29)$"
+ "|^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$"
+ "|^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$"
+ "|^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$");
@Override
public boolean matches(String date) {
return DATE_PATTERN.matcher(date).matches();
}
}
我們使用了"|"來匹配28天的、29天的、30天的、31天的,此時我們已經滿足了開始介紹的日期的所有約束
3.8 性能說明
解析複雜的表達式可能會影響性能。本文的主要目的主要是瞭解用正則來判斷日期的一種思路,如果要一種可靠且快速的方法來驗證日期,請考慮使用Java8提供的LocalDate.parse()。
四、總結
本文我們學習了使用正則表達式從格式、範圍和月份長度等規則匹配西曆日期。