Hôm nay, tôi nhận được email của 1 bạn đang mới bắt đầu học Java và hỏi về chủ đề mà tôi nghĩ khá hay và quan trọng đối với các bạn khi làm việc với kiểu dữ liệu ngày tháng.

Bạn Nguyễn Xuân Thương (ngansaohoitu.tbd@gmail.com) hỏi:

Sẵn đây anh giúp em cái này với
Em co cái hàm nhập ngày tháng như sau:

public static Date getDate(){
        boolean q=true;
        String ds;
        Date pDob = null;
        SimpleDateFormat fm=new SimpleDateFormat("dd-MM-yyyy");
        while(q){
            try{   
                ds=getString("nhap ngay sinh co dang dd-MM-yyyy:"+"\t");
                pDob=fm.parse(ds);
                q=false;
            }catch(ParseException e){}
        }
        return pDob;  
}

Như trên thì em phải nhập đúng đinh dạng dd-MM-yyyy thì được rồi, nhưng mà khì nhập vào ngày vd: 20-13-1994 thì nó lại in ra ngày 20-01-1995
Anh có cách nào ràng buộc cho nó nhập đúng ngày tháng thì giúp em với 
Cảm ơn anh nhiều!
Để kiểm tra dữ liệu Date, chúng ta có rất nhiều cách như xử lý Exception trong khi convert từ kiểu dữ liệu String sang Date, hay sub-string từng thành phần để kiểm tra, ... Những cách này vẫn cho được kết quả mong muốn nhưng xử lý logic có phần lằng nhằng và phức tạp.

Để tối ưu và đơn giản hóa việc kiểm tra dữ liệu Date, tôi sử dụng Regular Expression để xử lý các chuỗi ngày tháng.


Định dạng ngày tháng
Trong ví dụ này, tôi sẽ sử dụng định dạng ngày tháng như sau: dd/mm/yyyy

Date Format Regular Expression Pattern:

(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\\d\\d)
Pattern groups:
- Nhóm 1: (0?[1-9]|[12][0-9]|3[01]): bao gồm các ngày dạng 01-09, 1-9; 10-19, 20-29; 30-31
- Nhóm 2: (0?[1-9]|1[012]): bao gồm các tháng dạng 01-09, 1-9; 10, 11, 12
- Nhóm 3: ((19|20)\\d\\d): bao gồm các năm dạng 19xx, 20xx
Class DateUtils:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author code4lifevn
 */
public class DateUtils {

    private static Pattern dateRegexPattern = Pattern.compile("(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\\d\\d)");

    public static boolean isValidDate(String dateString) {
        Matcher dateMatcher = dateRegexPattern.matcher(dateString);

        if (dateMatcher.matches()) {

           dateMatcher.reset();

           if (dateMatcher.find()) {
               String day = dateMatcher.group(1);
               String month = dateMatcher.group(2);
               int year = Integer.parseInt(dateMatcher.group(3));

               if ("31".equals(day) && 
                  ("4".equals(month) || "6".equals(month) || "9".equals(month) ||
                   "11".equals(month) || "04".equals(month) || "06".equals(month) || 
                   "09".equals(month))) {
                   return false; // 1, 3, 5, 7, 8, 10, 12 has 31 days
               } else if ("2".equals(month) || "02".equals(month)) {
                    //leap year
                    if (year % 4 == 0) {
                        return !"30".equals(day) && !"31".equals(day);
                    } else {
                        return !"29".equals(day) && !"30".equals(day) && !"31".equals(day);
                    }
               } else {
                   return true;
               }
           } else {
               return false;
           }
        } else {
            return false;
        }
    }
}

Class DateTester:

/**
 *
 * @author code4lifevn
 */
public class DateTester {
    public static void main(String[] args) {
        String[] dates = {
              "20/10/2013",
              "08/03/2013",
              "a5/07/2013",
              "5/7/1990",
              "31/11/2013",
              "31/06/2013"
        };
 
        for (String date : dates) {
            System.out.println(DateUtils.isValidDate(date) ? "PASSED: " + date : "FAIL: " + date);
        }
    }
}

Output:
PASSED: 20/10/2013
PASSED: 08/03/2013
FAIL: a5/07/2013
PASSED: 5/7/1990
FAIL: 31/11/2013
FAIL: 31/06/2013


Hy vọng bài viết này sẽ giúp bạn trong quá trình học tập và làm việc hiệu quả!

4 nhận xét:

  1. Em sử dụng cách này nhanh cực:

    public static boolean isValidDate(String date) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    try {
    dateFormat.setLenient(false);
    dateFormat.parse(date);
    return true;
    } catch (Exception e) {
    return false;
    }
    }


    Mấu chốt ở dòng setLenient(false).

    Trả lờiXóa
  2. Date d= sdf.parse(""); // lỗi ở đây nó báo là định dạng không phù hợp

    -> Như vậy là đúng rồi mà bạn vì chuỗi bạn truyền vào là rỗng nên nó không parse được

    Trả lờiXóa
  3. import java.util.regex.Matcher;

    import java.util.regex.Pattern;

    public class DateValidator {

    public static final String PATTERN = "^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\\d\\d)$"; // ? la {0,1} va \d la [0-9]

    private Matcher matcher;

    public boolean validate(final String s){

    matcher=Pattern.compile(PATTERN).matcher(s);

    if(matcher.matches()){

    matcher.reset();

    if (matcher.find()){

    int year = Integer.parseInt(matcher.group(3));

    int[] dayMonth = {31,28,31,30,31,30,31,31,30,31,30,31};

    if ( ( year % 400 == 0 ) || ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) ) {

    if(Integer.parseInt(matcher.group(2))==2){

    dayMonth[1]=29;

    }

    }

    if(Integer.parseInt(matcher.group(1))<=dayMonth[Integer.parseInt(matcher.group(2))-1]){

    return true;

    }

    }

    }

    return false;

    }





    public static void main(String[] args) {

    DateValidator d = new DateValidator();

    System.out.println(d.validate("29/2/1991"));

    }



    }

    Trả lờiXóa

 

code4lifevn team

Thanh niên nghiêm túc :)

Name: Manh Do

Age: years old

Job: Senior Java and Mobile Developer

Country: VietNam

Name: Hung Nguyen

Age: years old

Job: Android Developer

Country: VietNam

Name: Trung PH

Age: years old

Job: Senior iOS and Android Developer

Country: VietNam

Name: Điệp NT

Age: years old

Job: Senior .Net and Android Developer

Country: VietNam