Cách kiểm tra một ngày trong Java [đã đóng]


83

Tôi thấy tò mò rằng cách rõ ràng nhất để tạo Datecác đối tượng trong Java đã không còn được dùng nữa và dường như đã được "thay thế" bằng cách sử dụng lịch khoan dung không quá rõ ràng.

Làm cách nào để bạn kiểm tra xem một ngày, được cho dưới dạng kết hợp của ngày, tháng và năm, có phải là ngày hợp lệ không?

Ví dụ: 2008-02-31 (như trong yyyy-mm-dd) sẽ là một ngày không hợp lệ.


Đối với bất kỳ ai có câu hỏi tương tự, vui lòng cân nhắc xem bạn có cần hỗ trợ lịch không phải của Gregorian hay không.
MSalters

@JasonC Tôi hoàn toàn đồng ý với bạn, hợp nhất chúng có vẻ là cách tốt nhất.
acm

Câu trả lời:


37

Cách hiện tại là sử dụng lớp lịch. Nó có phương thức setLenient sẽ xác thực ngày và ném và ngoại lệ nếu nó nằm ngoài phạm vi như trong ví dụ của bạn.

Quên thêm: Nếu bạn nhận được một phiên bản lịch và đặt thời gian bằng ngày của bạn, thì đây là cách bạn có được xác thực.

Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
    cal.getTime();
}
catch (Exception e) {
  System.out.println("Invalid date");
}

2
không nghĩ rằng điều này chính xác hoạt động như hiện tại. Calendar.setTime lấy java.util.Date, vì vậy quá trình chuyển đổi từ chuỗi đã xảy ra vào thời điểm bạn nhận được đối tượng "yourDate".
trễ

32
3 vấn đề với mã ví dụ: 1. Sau khi nhận được một phiên bản Lịch, bạn phải gọi cal.setLenient (false). Nếu không, một ngày như ngày 31 tháng 2 năm 2007 sẽ được coi là hợp lệ. 2. Một ngoại lệ không bị ném bởi cal.setTime (). Bạn phải gọi cal.getTime () sau lệnh gọi setTime (), lệnh này sẽ ném ra một ngoại lệ vào ngày không hợp lệ. 3. Đánh máy: Thiếu dấu '}' trước câu bắt.
Liron Yahdav

Điều này cũng chậm hơn so với các cách tiếp cận khác. Xem stackoverflow.com/questions/2149680/…
despot,

5
FYI, người già lớp ngày thời gian phiền hà như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là di sản , thay thế bởi sự java.time class built vào Java 8 và sau đó. Xem Hướng dẫn của Oracle .
Basil Bourque

3
không xác nhận ngày như ngày 31 tháng 2
Shikha singh

78

Khóa là df.setLenient (false); . Điều này là quá đủ cho những trường hợp đơn giản. Nếu bạn đang tìm kiếm một thư viện mạnh mẽ hơn (tôi nghi ngờ) và / hoặc thay thế như joda-time thì hãy xem câu trả lời của người dùng "tardate"

final static String DATE_FORMAT = "dd-MM-yyyy";

public static boolean isDateValid(String date) 
{
        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
}

2
Hãy thử với "09-04-201a". Nó sẽ tạo ra một cuộc hẹn hò điên cuồng.
ceklock

@ceklock đó là cách nó hoạt động, bất kể bạn có sử dụng setLenienthay không: SimpleDateFormatsẽ luôn phân tích cú pháp cho đến khi mẫu được khớp và bỏ qua phần còn lại của chuỗi, do đó bạn nhận được 201như năm.
Daniel Naber

@ceklock Tôi vừa giải quyết nó trong giải pháp của mình . Nó có thể tiết kiệm một hoặc hai phút cho ai đó.
Sufian

1
Việc kết hợp xử lý ngoại lệ dẫn đến một cú đánh hiệu suất lớn, vì vậy đây có thể là một thiết kế tồi NẾU bạn mong đợi đầu vào không đúng định dạng trong hoạt động bình thường (ví dụ: xác thực đầu vào của người dùng). Nhưng nếu phương pháp này được sử dụng như một kiểm tra kỹ các đầu vào được cho là hợp lệ mọi lúc (ngoại trừ lỗi), thì nó vẫn ổn.
Aaron

2
FYI, người già lớp ngày thời gian khủng khiếp phiền hà như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là di sản , thay thế bởi sự java.time class built vào Java 8 và sau đó. Xem Hướng dẫn của Oracle .
Basil Bourque

48

Như được hiển thị bởi @Maglob, cách tiếp cận cơ bản là kiểm tra chuyển đổi từ chuỗi sang ngày bằng cách sử dụng SimpleDateFormat.parse . Điều đó sẽ bắt các kết hợp ngày / tháng không hợp lệ như 2008-02-31.

Tuy nhiên, trong thực tế, điều đó hiếm khi là đủ vì SimpleDateFormat.parse cực kỳ tự do. Có hai hành vi mà bạn có thể quan tâm:

Các ký tự không hợp lệ trong chuỗi ngày Đáng ngạc nhiên là 2008-02-2x sẽ "chuyển" thành một ngày hợp lệ với định dạng miền địa phương = "yyyy-MM-dd" chẳng hạn. Ngay cả khi isLenient == false.

Năm: 2, 3 hoặc 4 chữ số? Bạn cũng có thể muốn thực thi năm 4 chữ số thay vì cho phép hành vi SimpleDateFormat mặc định (sẽ diễn giải "12-02-31" khác nhau tùy thuộc vào việc định dạng của bạn là "yyyy-MM-dd" hay "yy-MM-dd" )

Một giải pháp nghiêm ngặt với Thư viện chuẩn

Vì vậy, một kiểm tra chuỗi hoàn chỉnh cho đến nay có thể trông như thế này: kết hợp của đối sánh regex và sau đó là chuyển đổi ngày bắt buộc. Mẹo với regex là làm cho nó thân thiện với ngôn ngữ.

  Date parseDate(String maybeDate, String format, boolean lenient) {
    Date date = null;

    // test date string matches format structure using regex
    // - weed out illegal characters and enforce 4-digit year
    // - create the regex based on the local format string
    String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
    reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
    if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {

      // date string matches format structure, 
      // - now test it can be converted to a valid date
      SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
      sdf.applyPattern(format);
      sdf.setLenient(lenient);
      try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
    } 
    return date;
  } 

  // used like this:
  Date date = parseDate( "21/5/2009", "d/M/yyyy", false);

Lưu ý rằng regex giả định chuỗi định dạng chỉ chứa các ký tự ngày, tháng, năm và dấu phân tách. Bên cạnh đó, định dạng có thể ở bất kỳ định dạng ngôn ngữ nào: "d / MM / yy", "yyyy-MM-dd", v.v. Chuỗi định dạng cho ngôn ngữ hiện tại có thể được lấy như sau:

Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();

Joda Time - Giải pháp thay thế tốt hơn?

Tôi đã nghe nói về thời gian joda gần đây và nghĩ rằng tôi sẽ so sánh. Hai điểm:

  1. Có vẻ như nghiêm ngặt hơn về các ký tự không hợp lệ trong chuỗi ngày tháng, không giống như SimpleDateFormat
  2. Chưa thể thấy cách thực thi năm 4 chữ số với nó (nhưng tôi đoán bạn có thể tạo DateTimeFormatter của riêng mình cho mục đích này)

Nó khá đơn giản để sử dụng:

import org.joda.time.format.*;
import org.joda.time.DateTime;

org.joda.time.DateTime parseDate(String maybeDate, String format) {
  org.joda.time.DateTime date = null;
  try {
    DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
    date =  fmt.parseDateTime(maybeDate);
  } catch (Exception e) { }
  return date;
}

Tôi đã kết thúc với giải pháp thay thế joda và tự mình kiểm tra xem giá trị có khớp với độ dài mẫu hay không ...
Xtreme Biker

Cập nhật: khủng khiếp Các lớp di sản cũ ( Date, SimpleDateFormat, vv) đang thay thế bởi sự hiện đại java.time lớp. Tương tự như vậy, dự án Joda-Time đang ở chế độ bảo trì và khuyên bạn nên chuyển sang các lớp java.time .
Basil Bourque

38

Bạn có thể sử dụng SimpleDateFormat

Ví dụ một cái gì đó như:

boolean isLegalDate(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setLenient(false);
    return sdf.parse(s, new ParsePosition(0)) != null;
}

2
Một trong những vấn đề với cách tiếp cận này là nó sẽ chấp nhận 0003-0002-001.
despot

1
Một vấn đề khác là cài đặt 13 trong tháng trả về Ngày trong đó tháng là 01 vào năm sau.
8bitjunkie 13/12/13

FYI, người già lớp ngày thời gian khủng khiếp phiền hà như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là di sản , thay thế bởi sự java.time class built vào Java 8 và sau đó. Xem Hướng dẫn của Oracle .
Basil Bourque

28

tl; dr

Sử dụng chế độ nghiêm ngặt bật java.time.DateTimeFormatterđể phân tích cú pháp a LocalDate. Bẫy cho DateTimeParseException.

LocalDate.parse(                   // Represent a date-only value, without time-of-day and without time zone.
    "31/02/2000" ,                 // Input string.
    DateTimeFormatter              // Define a formatting pattern to match your input string.
    .ofPattern ( "dd/MM/uuuu" )
    .withResolverStyle ( ResolverStyle.STRICT )  // Specify leniency in tolerating questionable inputs.
)

Sau khi phân tích cú pháp, bạn có thể kiểm tra giá trị hợp lý. Ví dụ, ngày sinh trong vòng một trăm năm qua.

birthDate.isAfter( LocalDate.now().minusYears( 100 ) )

Tránh các lớp ngày-giờ kế thừa

Tránh sử dụng các lớp date-time cũ rắc rối được vận chuyển cùng với các phiên bản Java sớm nhất. Bây giờ được thay thế bởi các lớp java.time .

LocalDate& DateTimeFormatter&ResolverStyle

Các LocalDatelớp đại diện cho một giá trị ngày tháng chỉ mà không cần thời gian của ngày và không có múi giờ.

String input = "31/02/2000";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu" );
try {
    LocalDate ld = LocalDate.parse ( input , f );
    System.out.println ( "ld: " + ld );
} catch ( DateTimeParseException e ) {
    System.out.println ( "ERROR: " + e );
}

Các java.time.DateTimeFormatterlớp có thể được thiết lập để phân tích chuỗi với bất kỳ ba chế độ khoan dung quy định tại các ResolverStyleenum. Chúng tôi chèn một dòng vào đoạn mã trên để thử từng chế độ.

f = f.withResolverStyle ( ResolverStyle.LENIENT );

Kết quả:

  • ResolverStyle.LENIENT
    ld: 2000-03-02
  • ResolverStyle.SMART
    ld: 2000-02-29
  • ResolverStyle.STRICT
    LỖI: java.time.format.DateTimeParseException: Không thể phân tích cú pháp văn bản '31 / 02/2000 ': Ngày không hợp lệ' NGÀY 31 THÁNG 2 '

Chúng ta có thể thấy rằng trong ResolverStyle.LENIENTchế độ này, ngày không hợp lệ được chuyển về phía trước một số ngày tương đương. Ở ResolverStyle.SMARTchế độ (mặc định), một quyết định hợp lý được đưa ra để giữ ngày trong tháng và đi với ngày cuối cùng có thể của tháng, ngày 29 tháng 2 trong năm nhuận, vì không có ngày thứ 31 trong tháng đó. Các ResolverStyle.STRICTchế độ ném một ngoại lệ phàn nàn rằng không có ngày đó.

Cả ba điều này đều hợp lý tùy thuộc vào vấn đề kinh doanh và chính sách của bạn. Có vẻ như trong trường hợp của bạn, bạn muốn chế độ nghiêm ngặt từ chối ngày không hợp lệ hơn là điều chỉnh nó.


Bảng tất cả các kiểu ngày-giờ trong Java, cả hiện đại và kế thừa.


Giới thiệu về java.time

Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date, Calendar, & SimpleDateFormat.

Để tìm hiểu thêm, hãy xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của mình. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp.

Lấy các lớp java.time ở đâu?

Bảng sử dụng thư viện java.time với phiên bản Java hoặc Android nào

Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là cơ sở chứng minh cho những bổ sung có thể có trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval, YearWeek, YearQuarter, và nhiều hơn nữa .


Giả sử rằng dự án đang được biên dịch bằng java 8+, thì câu trả lời của bạn là đúng. Tôi cũng đang sử dụng các lớp này khi dự án ở java 8. Nhưng đôi khi tôi phải chạm vào những jsp scriptlets cổ điển xấu xí đó (thậm chí không hỗ trợ java 7). Xác thực ngày tháng có một khó khăn. Do đó tôi ở đây. Tuy nhiên, câu trả lời của bạn là cách tiếp cận đúng nhất ... Kết luận: Tôi đã bị hỏng.
KarelG

@KarelG Đọc lại đoạn văn thứ hai đến cuối cùng về cổng quay lại sang Java 6 & Java 7 . Tôi chưa xác minh hành vi này trong cổng sau nhưng tôi khuyên bạn nên thử.
Basil Bourque

13

java.time

Với API Ngày và Giờ ( các lớp java.time ) được tích hợp trong Java 8 trở lên, bạn có thể sử dụng LocalDatelớp này.

public static boolean isDateValid(int year, int month, int day) {
    boolean dateIsValid = true;
    try {
        LocalDate.of(year, month, day);
    } catch (DateTimeException e) {
        dateIsValid = false;
    }
    return dateIsValid;
}

2
Theo mặc định, mã này sử dụng ResolverStyle.SMARTđể điều chỉnh giá trị kết quả thành một ngày hợp lệ thay vì đưa ra một ngoại lệ. Vì vậy mã này sẽ không hoàn thành mục tiêu của Câu hỏi. Hãy xem Câu trả lời của tôi để biết ví dụ và giải pháp sử dụng ResolverStyle.STRICT.
Basil Bourque

7

Một giải pháp nghiêm ngặt thay thế bằng cách sử dụng thư viện tiêu chuẩn là thực hiện những điều sau:

1) Tạo SimpleDateFormat nghiêm ngặt bằng cách sử dụng mẫu của bạn

2) Cố gắng phân tích cú pháp giá trị do người dùng nhập bằng đối tượng định dạng

3) Nếu thành công, hãy định dạng lại Ngày kết quả từ (2) bằng cách sử dụng cùng một định dạng ngày (từ (1))

4) So sánh ngày được định dạng lại với giá trị ban đầu do người dùng nhập. Nếu chúng bằng nhau thì giá trị đã nhập hoàn toàn khớp với mẫu của bạn.

Bằng cách này, bạn không cần tạo các biểu thức chính quy phức tạp - trong trường hợp của tôi, tôi cần hỗ trợ tất cả cú pháp mẫu của SimpleDateFormat, thay vì bị giới hạn ở một số loại nhất định như chỉ ngày, tháng và năm.


Đây chắc chắn là con đường để đi, xem thêm mẫu mã trên dreamincode.net/forums/topic/...
Victor Ionescu

7

Dựa trên câu trả lời của Aravind để khắc phục sự cố được ceklock chỉ ra trong nhận xét của anh ấy , tôi đã thêm một phương pháp để xác minh rằng câu trả lờidateString không chứa bất kỳ ký tự không hợp lệ nào.

Đây là cách tôi làm:

private boolean isDateCorrect(String dateString) {
    try {
        Date date = mDateFormatter.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return matchesOurDatePattern(dateString);    //added my method
    }
    catch (ParseException e) {
        return false;
    }
}

/**
 * This will check if the provided string matches our date format
 * @param dateString
 * @return true if the passed string matches format 2014-1-15 (YYYY-MM-dd)
 */
private boolean matchesDatePattern(String dateString) {
    return dateString.matches("^\\d+\\-\\d+\\-\\d+");
}

4

Tôi đề nghị bạn sử dụng org.apache.commons.validator.GenericValidatorlớp từ apache.

GenericValidator.isDate(String value, String datePattern, boolean strict);

Lưu ý: nghiêm ngặt - Có khớp chính xác với datePattern hay không.


4

Tôi nghĩ đơn giản nhất chỉ là chuyển đổi một chuỗi thành một đối tượng ngày tháng và chuyển nó trở lại thành chuỗi. Chuỗi ngày đã cho sẽ ổn nếu cả hai chuỗi vẫn khớp.

public boolean isDateValid(String dateString, String pattern)
{   
    try
    {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        if (sdf.format(sdf.parse(dateString)).equals(dateString))
            return true;
    }
    catch (ParseException pe) {}

    return false;
}

2

Giả sử rằng cả hai đều là Chuỗi (nếu không thì chúng đã là Ngày hợp lệ), đây là một cách:

package cruft;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateValidator
{
    private static final DateFormat DEFAULT_FORMATTER;

    static
    {
        DEFAULT_FORMATTER = new SimpleDateFormat("dd-MM-yyyy");
        DEFAULT_FORMATTER.setLenient(false);
    }

    public static void main(String[] args)
    {
        for (String dateString : args)
        {
            try
            {
                System.out.println("arg: " + dateString + " date: " + convertDateString(dateString));
            }
            catch (ParseException e)
            {
                System.out.println("could not parse " + dateString);
            }
        }
    }

    public static Date convertDateString(String dateString) throws ParseException
    {
        return DEFAULT_FORMATTER.parse(dateString);
    }
}

Đây là kết quả tôi nhận được:

java cruft.DateValidator 32-11-2010 31-02-2010 04-01-2011
could not parse 32-11-2010
could not parse 31-02-2010
arg: 04-01-2011 date: Tue Jan 04 00:00:00 EST 2011

Process finished with exit code 0

Như bạn có thể thấy, nó xử lý tốt cả hai trường hợp của bạn.


@duffymo tuyên bố thứ hai không phải là ngoại lệ ... :(
maximus

@Pangea Không thực sự .... hãy thử ngày "31-01-2010" nó sẽ không có ngoại lệ nào .......... Chỉ cần chạy nó trên máy của bạn và xem ... nó không công việc ....
sasidhar

Lỗi của tôi. Tôi đã xóa bình luận của mình. Tuy nhiên, tuyên bố thứ hai là ném ngoại lệ cho tôi. @duffymo - bạn đang sử dụng jvm nào?
Aravind Yarram

@Pangea tôi đang sử dụng jdk1.6.0_23 Tôi cố gắng này với điều này thậm chí joda-time.sourceforge.net nhưng tất cả đều không làm việc ....
sasidhar

1
Tôi hiểu đây chỉ là một bài kiểm tra đơn giản nhưng để đảm bảo rằng mọi người không sao chép nguyên văn bài kiểm tra này, tôi muốn nói rằng "DateFormat" KHÔNG AN TOÀN. Vì vậy, hãy luôn tạo nó như một biến cục bộ hoặc sử dụng nó với cục bộ luồng.
Aravind Yarram

2

Điều này đang làm việc tuyệt vời cho tôi. Cách tiếp cận do Ben đề xuất ở trên.

private static boolean isDateValid(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    try {
        Date d = asDate(s);
        if (sdf.format(d).equals(s)) {
            return true;
        } else {
            return false;
        }
    } catch (ParseException e) {
        return false;
    }
}

1
không thể nhận dạng asDate. Đó là gì?
Susheel

2

có vẻ như SimpleDateFormat không kiểm tra mẫu một cách nghiêm ngặt ngay cả sau setLenient (false); phương thức được áp dụng trên nó, vì vậy tôi đã sử dụng phương thức dưới đây để xác thực xem ngày nhập vào có phải là ngày hợp lệ hay không theo mẫu được cung cấp.

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public boolean isValidFormat(String dateString, String pattern) {
    boolean valid = true;
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    try {
        formatter.parse(dateString);
    } catch (DateTimeParseException e) {
        valid = false;
    }
    return valid;
}

1

Hai nhận xét về việc sử dụng SimpleDateFormat.

nó nên được khai báo là một trường hợp tĩnh nếu được khai báo là truy cập tĩnh phải được đồng bộ hóa vì nó không an toàn cho chuỗi

IME tốt hơn là tạo một phiên bản cho mỗi phân tích cú pháp của một ngày.


điểm tốt Tom. Tôi đã cập nhật ví dụ mà tôi cung cấp để đảm bảo sử dụng phiên bản tĩnh một cách nhất quán.
trễ

Sử dụng một chức năng đồng bộ hóa có thể không mở rộng cho một số dự án. Tôi sẽ nhắc lại việc đặt SimpleDateFormat trong một biến ThreadLocal thay vì một biến tĩnh được truy cập thông qua một hàm được đồng bộ hóa.
user327961

0

Các phương pháp phân tích ngày tháng ở trên rất hay, tôi vừa thêm kiểm tra mới vào các phương pháp hiện có để kiểm tra kỹ ngày đã chuyển đổi với ngày ban đầu bằng cách sử dụng trình định dạng, vì vậy nó hoạt động cho hầu hết mọi trường hợp khi tôi đã xác minh. ví dụ: 02/29/2013 là ngày không hợp lệ. Hàm đã cho phân tích cú pháp ngày theo các định dạng ngày được chấp nhận hiện tại. Nó trả về true nếu ngày không được phân tích cú pháp thành công.

 public final boolean validateDateFormat(final String date) {
        String[] formatStrings = {"MM/dd/yyyy"};
        boolean isInvalidFormat = false;
        Date dateObj;
        for (String formatString : formatStrings) {
            try {
                SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateInstance();
                sdf.applyPattern(formatString);
                sdf.setLenient(false);
                dateObj = sdf.parse(date);
                System.out.println(dateObj);
                if (date.equals(sdf.format(dateObj))) {
                    isInvalidFormat = false;
                    break;
                }
            } catch (ParseException e) {
                isInvalidFormat = true;
            }
        }
        return isInvalidFormat;
    }

0

Đây là những gì tôi đã làm cho môi trường Node không sử dụng thư viện bên ngoài:

Date.prototype.yyyymmdd = function() {
   var yyyy = this.getFullYear().toString();
   var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
   var dd  = this.getDate().toString();
   return zeroPad([yyyy, mm, dd].join('-'));  
};

function zeroPad(date_string) {
   var dt = date_string.split('-');
   return dt[0] + '-' + (dt[1][1]?dt[1]:"0"+dt[1][0]) + '-' + (dt[2][1]?dt[2]:"0"+dt[2][0]);
}

function isDateCorrect(in_string) {
   if (!matchesDatePattern) return false;
   in_string = zeroPad(in_string);
   try {
      var idate = new Date(in_string);
      var out_string = idate.yyyymmdd();
      return in_string == out_string;
   } catch(err) {
      return false;
   }

   function matchesDatePattern(date_string) {
      var dateFormat = /[0-9]+-[0-9]+-[0-9]+/;
      return dateFormat.test(date_string); 
   }
}

Và đây là cách sử dụng nó:

isDateCorrect('2014-02-23')
true

0
// to return valid days of month, according to month and year
int returnDaysofMonth(int month, int year) {
    int daysInMonth;
    boolean leapYear;
    leapYear = checkLeap(year);
    if (month == 4 || month == 6 || month == 9 || month == 11)
        daysInMonth = 30;
    else if (month == 2)
        daysInMonth = (leapYear) ? 29 : 28;
    else
        daysInMonth = 31;
    return daysInMonth;
}

// to check a year is leap or not
private boolean checkLeap(int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}

0

Đây là tôi sẽ kiểm tra định dạng ngày:

 public static boolean checkFormat(String dateTimeString) {
    return dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}") || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}")
            || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}") || dateTimeString
            .matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z") ||
            dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}Z");
}

Chúng tôi có các lớp java.time hiện đại cho công việc này ngay bây giờ. Viết regex phức tạp không phải là cách sử dụng thời gian tốt nhất của bạn. Xem phần lót một trong Câu trả lời của tôi .
Basil Bourque

0
        public static String detectDateFormat(String inputDate, String requiredFormat) {
        String tempDate = inputDate.replace("/", "").replace("-", "").replace(" ", "");
        String dateFormat;

        if (tempDate.matches("([0-12]{2})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMddyyyy";
        } else if (tempDate.matches("([0-31]{2})([0-12]{2})([0-9]{4})")) {
            dateFormat = "ddMMyyyy";
        } else if (tempDate.matches("([0-9]{4})([0-12]{2})([0-31]{2})")) {
            dateFormat = "yyyyMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([0-12]{2})")) {
            dateFormat = "yyyyddMM";
        } else if (tempDate.matches("([0-31]{2})([a-z]{3})([0-9]{4})")) {
            dateFormat = "ddMMMyyyy";
        } else if (tempDate.matches("([a-z]{3})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMMddyyyy";
        } else if (tempDate.matches("([0-9]{4})([a-z]{3})([0-31]{2})")) {
            dateFormat = "yyyyMMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([a-z]{3})")) {
            dateFormat = "yyyyddMMM";
        } else {
            return "Pattern Not Added";
//add your required regex
        }
        try {
            String formattedDate = new SimpleDateFormat(requiredFormat, Locale.ENGLISH).format(new SimpleDateFormat(dateFormat).parse(tempDate));

            return formattedDate;
        } catch (Exception e) {
            //
            return "";
        }

    }

0

Với định dạng ngày 'kế thừa', chúng tôi có thể định dạng kết quả và so sánh nó trở lại nguồn.

    public boolean isValidFormat(String source, String pattern) {
    SimpleDateFormat sd = new SimpleDateFormat(pattern);
    sd.setLenient(false);
    try {
        Date date = sd.parse(source);
        return date != null && sd.format(date).equals(source);
    } catch (Exception e) {
        return false;
    }
}

Trình thực thi này cho biết 'false' thành source = 01.01.04 với mẫu '01 .01.2004 '


-1

setLenient thành false nếu bạn muốn xác thực chặt chẽ

public boolean isThisDateValid(String dateToValidate, String dateFromat){

    if(dateToValidate == null){
        return false;
    }

    SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
    sdf.setLenient(false);

    try {

        //if not valid, it will throw ParseException
        Date date = sdf.parse(dateToValidate);
        System.out.println(date);

    } catch (ParseException e) {

        e.printStackTrace();
        return false;
    }

    return true;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.