날짜 정규 표현 식 에 대한 자세 한 설명

1        개술
우선 설명 이 필요 한 것 은 Winform 이 든 Webform 이 든 모두 성숙 한 달력 컨트롤 이 있 습 니 다.사용 하기 쉽 든 확장 가능 하 든 날짜 선택 과 검증 은 달력 컨트롤 로 하 는 것 이 좋 습 니 다.
며칠 전 CSDN 여러 판 에서 날짜 정칙 이 필요 한 게시 물 을 보고 이 글 을 정리 해 놓 고 여러분 과 함께 토론 하고 교류 하 며,누락 되 거나 잘못된 부분 이 있 으 면 지적 도 부탁 드린다.
날짜 정규 는 일반적으로 형식 에 대한 요구 가 있 고 데 이 터 는 사용자 가 직접 입력 할 때 사용 하 는 것 이 아니다.응용 장면 에 따라 쓴 정규 도 다 르 고 복잡 한 정도 도 자연히 다르다.정규 적 인 글 씨 는 구체 적 인 상황 에 따라 구체 적 으로 분석 해 야 한다.하나의 기본 원칙 은 적당 한 것 만 쓰 고 복잡 한 것 은 쓰 지 않 는 다 는 것 이다.
날짜 추출 에 대해 서 는 비 날짜 구역 과 분리 할 수 있 으 면 가장 간단 한 정규 를 쓰 면 됩 니 다.예 를 들 어

\d{4}-\d{2}-\d{2}
원본 문자열 에서 yyy-MM-dd 형식의 날 짜 를 유일 하 게 찾 을 수 있다 면 추출 할 수 있 습 니 다.
검증 에 있어 서 문자 구성 과 형식 만 검증 하 는 것 은 큰 의미 가 없 으 며 규칙 에 대한 검증 도 추가 해 야 합 니 다.윤년 의 존재 로 인해 날짜 의 검사 가 비교적 복잡 해 졌 다.
우선 날짜 의 유효 범위 와 윤년 이 무엇 인지 살 펴 보 자.
2       날짜 규칙
2.1     날짜 의 유효 범위
날짜 의 유효 범위 에 대해 서로 다른 응용 장면 이 다 를 수 있 습 니 다.
MSDN 에서 정의 한 DateTime 대상 의 유효 범 위 는 0001-01-01 00:00:00 부터 9999-12-31 23:59:59 입 니 다.
UNIX 타임 스탬프 의 0 은 ISO 8601 규범 에 따라 1970-01-01T 00:00:00 Z 이다.
실제 응용 에서 날짜 의 범 위 는 DateTime 이 규정 한 범 위 를 초과 하지 않 기 때문에 그 중에서 자주 사용 하 는 날짜 범 위 를 검증 하면 된다.
2.2     윤년 이란 무엇 인가
(이하 바 이 두 백과 에서 발췌)
윤년(leap year)은 사람 이 역법 에 규정된 연도 일수 와 지구의 실제 공전 주기의 시간 차 를 메 우기 위해 설립 된 것 이다.시 차 를 보충 한 해 는 윤년 이다.
지구 둘레 운행 주 기 는 365 일 5 시간 48 분 46 초(총 365.24219 일),즉 회귀 년(tropical year)이다.양력 의 평년 은 365 일 로 회귀 년 보다 약 0.2422 일 짧 고,4 년 마다 약 하루 씩 축 적 돼 이 날 을 2 월 말(즉 2 월 29 일)에 더 해 그해 기간 을 366 일 로 바 꾸 면 윤년 이 된다.
주의해 야 할 것 은 현재 의 양력 은 로마인 들 의'유 략 력'을 각색 한 것 이다.매년 0.0078 일 을 더 산출 해 야 한 다 는 문 제 를 당시 에 알 지 못 했 기 때문에 기원전 46 년 부터 16 세기 까지 모두 누적 10 일이 더 많아 졌 다.이 를 위해 당시 교황 그 레 고리 13 세 는 1582 년 10 월 5 일 을 10 월 15 일 로 규정 했다.새 윤년 규정 을 시작 했다.즉,양력 연 도 를 100 수로 정 하고 400 의 배수 가 윤년 이 어야 하 며 400 의 배수 가 아니면 평년 이 어야 한다.예 를 들 어 1700 년,1800 년,1900 년 은 평년 이 고 2000 년 은 윤년 이다.이후 매년 평균 길 이 는 365.2425 일 로 약 4 년 간 1 일의 편차 가 나 타 났 다.4 년 마다 윤년 을 계산 하면 매년 평균 0.0078 일 을 더 계산 하고 400 년 이 지나 면 약 3 일이 더 많아 지기 때문에 400 년 마다 윤년 을 3 개 씩 줄 여야 한다.윤년 의 계산 을 종합해 보면 흔히 말 하 는 4 년 1 윤 이다.백 년 은 윤달 하지 않 고,사 백 년 은 윤달 하 다.
2.3     날짜 형식
서로 다른 언어 문화 에 따라 날짜 의 연결 문자 가 다 를 수 있 고 보통 다음 과 같은 몇 가지 형식 이 있 습 니 다.
yyyyMMdd
yyyy-MM-dd
yyyy/MM/dd
yyyy.MM.dd
3       날짜 정규 표현 식 구축
3.1     규칙 분석
복잡 한 정규 를 쓰 는 데 자주 사용 되 는 방법 은 관련 되 지 않 은 수 요 를 분리 하고 해당 하 는 정규 를 각각 쓴 다음 에 조합 하여 상호 관련 관계 와 영향 을 검사 하면 대체적으로 대응 하 는 정규 를 얻 을 수 있다 는 것 이다.
윤년 의 정의 에 따 르 면 날 짜 는 몇 가지 분류 방법 이 있 을 수 있다.
3.1.1  일수 와 연도 의 관계 여부 에 따라 두 종류 로 나누다
연도 와 무관 한 부류 중 매월 일수 에 따라 두 종류 로 세분 할 수 있다
  • 1,3,5,7,8,10,12 월 은 1-31 일
  • 이다.
  • 4,6,9,11 월 은 1-30 일
  • 이다.
    연도 와 관련 된 부류 중
  • 평년 2 월 은 1-28 일
  • 윤년 2 월 은 1-29 일
  • 이다.
  • 모든 년도 의 모든 달 은 1-28 일
  • 을 포함한다.
  • 모든 연 도 는 2 월 을 제외 하고 29 일과 30 일
  • 을 포함한다.
  • 모든 년도 1,3,5,7,8,10,12 월 은 31 일
  • 을 포함한다.
  • 윤년 2 월 은 29 일
  • 을 포함한다.
    3.1.2  포함 날짜 에 따라 네 가지 로 나 눌 수 있 습 니 다.
    3.1.3  분류 방법 선택
    날짜 분류 후의 실현 은(exp1|exp2|exp 3)이러한 분기 구 조 를 통 해 이 루어 져 야 하기 때 문 입 니 다.분기 구 조 는 왼쪽 분기 에서 오른쪽으로 순서대로 매 칭 을 시도 합 니 다.한 분기 가 성공 하면 오른쪽으로 시도 하지 않 습 니 다.그렇지 않 으 면 모든 가 지 를 시도 한 후에 실 패 를 보고 합 니 다.
    분기 의 많 고 적 음,각 분기 의 복잡 정 도 는 일치 효율 에 영향 을 줄 수 있 습 니 다.검 증 된 날짜 의 확률 분 포 를 고려 하면 대부분 1-28 일 이내 에 떨 어 지기 때문에 두 번 째 분류 방법 을 사용 하면 일치 효율 을 효과적으로 높 일 수 있 습 니 다.
    3.2     정규 실현
    3.1.2 절의 분류 방법 을 사용 하면 모든 규칙 에 대응 하 는 정규 를 쓸 수 있 고 다음은 MM-dd 형식 으로 잠시 실현 할 수 있다.
    먼저 연도 와 무관 한 앞의 세 가지 규칙 을 고려 하면 연 도 는 통일 적 으로 글 을 쓸 수 있다.
    
    (?!0000)[0-9]{4}
    다음은 달 과 일의 정칙 만 을 고려한다.
    평년 을 포함 한 모든 연도 의 월 은 1~28 일 을 포함한다.
    
    (0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])
    평년 을 포함 한 모든 연 도 는 2 월 을 제외 하고 29 일과 30 일 을 포함한다.
    
    (0[13-9]|1[0-2])-(29|30)
    평년 을 포함 한 모든 연도 1,3,5,7,8,10,12 월 은 31 일 을 포함한다.
    
    (0[13578]|1[02])-31)
    합치 면 윤년 의 2 월 29 일 을 제외 한 모든 날짜 입 니 다.
    
    (?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)
    다음은 윤년 의 실현 을 고려 하 자.
    윤년 2 월 은 29 일 을 포함한다.
    이곳 의 달 과 날 은 고정 되 어 있 는데 바로 02-29 로 해 만 변화 한다.
    다음 코드 를 통 해 모든 윤년 연 도 를 출력 하고 규칙 을 고찰 할 수 있 습 니 다.
    
    for (int i = 1; i < 10000; i++){
      if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0){
       richTextBox2.Text += string.Format("{0:0000}", i) + "
    "; } }
    윤년 의 규칙 에 따라 규칙 을 쉽게 정리 하고 4 년 에 한 번 윤년 이 된다.
    
    ([0-9]{2}(0[48]|[2468][048]|[13579][26])
    백 년 은 윤달 하지 않 고,사 백 년 은 윤달 하 다.
    
    (0[48]|[2468][048]|[13579][26])00
    합치 면 모든 윤년 의 2 월 29 일이 다.
    
    ([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)
    네 가지 규칙 이 모두 실현 되 었 고 서로 영향 을 주지 않 았 습 니 다.합치 면 DateTime 범위 에 부합 되 는 모든 날짜 의 정규 입 니 다.
    
    ^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$
    이 정규 표현 식 은 검증 에 만 사용 되 기 때문에 포획 그룹 은 의미 가 없고 자원 만 차지 하여 일치 효율 에 영향 을 미 치기 때문에 비 포획 그룹 을 사용 하여 최적화 할 수 있다.
    
    ^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
    이상 정규 년도 0001-9999,형식 yyy-MM-dd.다음 코드 를 통 해 정규 의 유효성 과 성능 을 검증 할 수 있다.
    
    DateTime dt = new DateTime(1, 1, 1);
    DateTime endDay = new DateTime(9999, 12, 31);
    Stopwatch sw = new Stopwatch();
    sw.Start();
     
    Regex dateRegex = new Regex(@"^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$");
     
    //Regex dateRegex = new Regex(@"^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$");
    Console.WriteLine("    : " + dt.ToString("yyyy-MM-dd"));
    while (dt < endDay){
      if (!dateRegex.IsMatch(dt.ToString("yyyy-MM-dd"))){
       Console.WriteLine(dt.ToString("yyyy-MM-dd") + " false");
      }
      dt = dt.AddDays(1);
    }
    if (!dateRegex.IsMatch(dt.ToString("yyyy-MM-dd"))){
      Console.WriteLine(dt.ToString("yyyy-MM-dd") + " false");
    }
    Console.WriteLine("    : " + dt.ToString("yyyy-MM-dd"));
    sw.Stop();
    Console.WriteLine("    : " + sw.ElapsedMilliseconds + "ms");
    Console.WriteLine("    !");
    Console.ReadLine();
    4       날짜 정규 표현 식 확장
    4.1     “년 월 일
    이상 은 yyyy-MM-dd 형식의 날짜 검증 을 실 현 했 습 니 다.하이픈 의 차이 점 과 월 과 일이 M 과 d,즉 yyy-M-d 일 수 있 는 형식 을 고려 하여 상기 정규 를 확장 할 수 있 습 니 다.
    
    ^(?:(?!0000)[0-9]{4}([-/.]?)(?:(?:0?[1-9]|1[0-2])([-/.]?)(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])([-/.]?)(?:29|30)|(?:0?[13578]|1[02])([-/.]?)31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)([-/.]?)0?2([-/.]?)29)$
    역방향 인용 을 사용 하여 간소화 합 니 다.년도 0001-9999,형식 yyy-MM-dd 또는 yyy-M-d 는 문자 가 없 거나'-','/','.'중 하나 일 수 있 습 니 다.
    
    ^(?:(?!0000)[0-9]{4}([-/.]?)(?:(?:0?[1-9]|1[0-2])\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\1(?:29|30)|(?:0?[13578]|1[02])\1(?:31))|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)([-/.]?)0?2\2(?:29))$
    이것 이 바로'년 월 일'이라는 형식 이 가장 완전한 정규 이다.서로 다른 의미 부분 은 서로 다른 색채 로 표 지 를 하고 자신의 수요 에 따라 자 를 수 있다.
    4.2     기타 형식 확장
    상기 정규 각 부분의 대표 적 의 미 를 이해 한 후에 서로 간 의 관 계 를 이해 한 후에 다른 형식의 날짜 정규,예 를 들 어 d/MM/yyyy 와 같은'일월 년'형식의 날짜 로 확장 하기 쉽다.
    
    ^(?:(?:(?:0?[1-9]|1[0-9]|2[0-8])([-/.]?)(?:0?[1-9]|1[0-2])|(?:29|30)([-/.]?)(?:0?[13-9]|1[0-2])|31([-/.]?)(?:0?[13578]|1[02]))([-/.]?)(?!0000)[0-9]{4}|29([-/.]?)0?2([-/.]?)(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00))$
    이런 격식 이 주의해 야 할 것 은 역방향 인용 으로 우 위 를 진행 할 수 없다 는 것 이다.문자 등 은 자신의 수요 에 따라 재단 할 수 있다.
    4.3     시간 확장 추가
    시간의 규격 은 매우 명확 하고 간단 하 며 기본적으로 HH:mm:ss 와 H:m:s 두 가지 형식 이다.
    
    ([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]
    날짜 정규 에 합치 면 yyy-MM-dd HH:mm:ss
    
    ^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)\s+([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$
    4.4     연도 맞 춤 형 제작
    상기 모든 평년 과 관련 된 연도 에 사용 한 것 은 0001-9999 입 니 다.물론 연도 도 윤년 규칙 에 따라 맞 출 수 있다.
    예 를 들 어 년도 1600-9999,형식 yyy-MM-dd 또는 yyy-M-d 는 문자 가 없 거나'-','/','.'중 하나 일 수 있 습 니 다.
    
    ^(?:(?:1[6-9]|[2-9][0-9])[0-9]{2}([-/.]?)(?:(?:0?[1-9]|1[0-2])\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\1(?:29|30)|(?:0?[13578]|1[02])\1(?:31))|(?:(?:1[6-9]|[2-9][0-9])(?:0[48]|[2468][048]|[13579][26])|(?:16|[2468][048]|[3579][26])00)([-/.]?)0?2\2(?:29))$
    5       특별 설명
    이상 의 정규 규칙 은 가장 기본 적 인 정규 문법 규칙 을 사용 하 는데 대부분 전통 적 인 NFA 엔진 을 사용 하 는 언어 는 자 바스 크 립 트,자바,.NET 등 을 포함 하여 지원 할 수 있다.
    또한 필요 한 것 은 날짜 의 규칙 이 상대 적 으로 명확 하지만 이런 방식 으로 재단 하여 요구 에 부합 되 는 날짜 의 정규 를 얻 을 수 있 지만 이렇게 정규 를 사용 하 는 것 을 추천 하지 않 는 다.정규 의 강 함 은 그의 유연성 에 있다.수요 에 따라 몸 을 재 어 가장 적합 한 정규 를 만 들 수 있다.만약 에 템 플 릿 만 사용 하면 정규 라 고 부 르 지 않 는 다.
    정규 적 인 문법 규칙 이 많 지 않 고 입문 하기 쉬 우 며 문법 규칙 을 파악 하고 몸 에 맞 게 옷 을 재단 하 는 것 이 야 말로 정규 적 인'도'이다.
    6       활용 단어 참조
    첫째,우선 수요
    날짜 입력:
    수 동 입력,두 가지 형식 yyymmd 또는 yyy-mm-dd 입력 가능
    2.해결 방향
    사용자 가 수 동 으로 날 짜 를 입력 하려 면 입력 한 날짜 형식 을 검증 해 야 합 니 다.
    사용자 가 입력 할 수 있 는 상황 은 다음 과 같은 몇 가지 로 나 눌 수 있다.
    (1).빈 칸 또는 빈 칸 으로 입력
    (2).날짜 가 아 닌 형식 을 입력 하 십시오.
    데이터베이스 에 저 장 된 날짜 형식 에 따라 저 장 된 형식 은 yyy-mm-dd 이기 때문에 사용 자 는 yyymmd 를 입력 한 후 yyy-mm-dd 로 변환 해 야 합 니 다.
    생각:
    검증 날짜 형식 은 VS 의 검증 컨트롤 을 처음 생각 했 습 니 다.그러나 검증 이 필요 한 컨트롤 이 수 십 개 이기 때문에 검증 컨트롤 을 사용 하려 면 하나씩 컨트롤 을 당 겨 야 합 니 다.나중에 수정 이 필요 하 다 면 JS 를 통 해 제 어 를 하고 정규 표현 식 을 통 해 일 기 를 검증 해 야 합 니 다.
    3.JS 실현
    
    //    
    function date(id) {
      var idvalue = document.getElementById(id).value;  //      
      var tmpStr = "";
      var strReturn = "";
      //  trim()    ,  js   trim()
      var iIdNo = trim(idvalue);
      //     ,      ,       ,     ,     
      var v = idvalue.match(/^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$/);
      //         
      if (iIdNo.length == 0) {
        return false;
      }
      //         yyyy-mm-dd
      if (iIdNo.length == 8) {
        tmpStr = iIdNo.substring(0, 8);
        tmpStr = tmpStr.substring(0, 4) + "-" + tmpStr.substring(4, 6) + "-" + tmpStr.substring(6, 8)
        document.getElementById(id).value = tmpStr;
        document.getElementById(id).focus();
      }
      //  ,      
      if ((iIdNo.length != 8) && !v) {
        strReturn = "      ,  :19990101 1999-01-01";
        alert(strReturn);
        document.getElementById(id).select();
        return false;
      }
    }
    //                (  js   trim()) 
    function trim(str) {
      return str.replace(/(^\s*)|(\s*$)/g, "");
    }
    //    (      )
    <input class="txtenterschooldate" size="14" type="text" id="txtenterschooldate" name="txtenterschooldate" onblur="date('txtenterschooldate')"/>
    총결산
    위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 날짜 정규 표현 식 에 대한 사고 에 대한 상세 한 설명 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.만약 에 궁금 한 점 이 있 으 면 저 에 게 메 시 지 를 남 겨 주세요.소 편 은 제때에 여러분 에 게 답 할 것 입 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기