2011-09-30 59 views
43

Ở đây lenient được sử dụng trong Java DateFormat. Tôi đã kiểm tra tài liệu, nhưng không hiểu nó đang nói gì.Việc sử dụng "khoan dung" là gì?

Mọi người có thể vui lòng cho tôi biết việc sử dụng số điện thoại lenient này là gì, với một ví dụ thời gian thực mà chúng tôi sử dụng?

+1

FYI, 'DateFormat' là một trong những lớp học ngày thời gian cũ phiền hà mà bây giờ là di sản, thay thế bằng các lớp java.time. Sử dụng ['java.time.format.DateTimeFormatter'] (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html). –

Trả lời

4

Bạn có thể đặt trình phân tích cú pháp ngày không khoan dung nếu bạn muốn nó chấp nhận đúng định dạng ngày bạn đã cung cấp. Nó được giải thích trong the doc:

Theo mặc định, phân tích cú pháp là nhân hậu: Nếu đầu vào không có trong các hình thức sử dụng bằng phương pháp định dạng của đối tượng này, nhưng vẫn có thể được phân tích như một ngày, sau đó phân tích cú pháp thành công. Khách hàng có thể khăng khăng tuân thủ nghiêm ngặt định dạng bằng cách gọi số setLenient(false).

20

Ví dụ này:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy"); 
System.out.println(simpleDateFormat.parse("0")); 
simpleDateFormat.setLenient(false); 
System.out.println(simpleDateFormat.parse("0")); 

kết quả trong:

Thu Jan 01 00:00:00 CET 1 
Exception in thread "main" java.text.ParseException: Unparseable date: "0" 
    at java.text.DateFormat.parse(Unknown Source) 
    at net.java.quickcheck.generator.support.X.main(X.java:28) 
+2

Tại sao mã sau hoạt động. ? SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("yyyy"); \t \t \t System.out.println (simpleDateFormat.parse ("4")); \t \t \t simpleDateFormat.setLenient (false); \t \t \t System.out.println (simpleDateFormat.parse ("4")); – KSHiTiJ

+0

Nguyên nhân ở đó (trong Lịch Gregorian là mặc định của Java) không phải là năm "0". Sau 1 BC (sẽ chuyển thành -1 AFAIK) theo sau 1 AD (nghĩa là, tốt, 1). Vì vậy, "0" ở trên là (leniently) được coi là "0 năm (sau năm đầu tiên, đó là 1)" và kết quả trong 1. Nếu phân tích cú pháp được tắt, ngoại lệ được ném. Nói cách khác, bạn không kiểm tra đầu vào 4 chữ số được định dạng tốt bằng mã đó. (Thậm chí 300 AD, "300" sẽ là một năm yyyy hợp lệ, tất nhiên) – chammp

40

Các javadoc nêu rõ:

Xác định có hay không ngày/giờ phân tích cú pháp là để được khoan dung . Với phân tích cú pháp khoan dung, trình phân tích cú pháp có thể sử dụng chẩn đoán để giải thích đầu vào không khớp chính xác với định dạng của đối tượng này. Với phân tích cú pháp nghiêm ngặt, các đầu vào phải khớp với định dạng của đối tượng này.

Vì vậy, nếu bạn có một mô hình và tạo ra một đối tượng ngày đó Nghiêm phù hợp với mô hình của bạn, thiết lập nhân hậu để false. Ngoài ra, theo mặc định, theo mặc định, DateFormat là ưu điểm.

Về cơ bản, DateFormat bộ Calendar.setLenient và các bang Javadoc:

Chỉ định có hay không ngày/giờ giải thích là để được khoan dung. Với cách diễn dịch khoan dung, một ngày như "tháng 2 năm 942, 1996" sẽ được coi là tương đương với ngày thứ 941 sau ngày 1 tháng 2, 1996. Với diễn giải nghiêm ngặt (không khoan dung), những ngày như vậy sẽ gây ra bị ném. Mặc định là khoan dung.

+34

Câu hỏi của tôi sẽ là, tại sao trái đất là 'lenient' _true_ theo mặc định! Nó sẽ có ý nghĩa hơn với tôi nếu nó là _false_ theo mặc định, bởi vì các lập trình viên, đặc biệt là người mới bắt đầu, sẽ có xu hướng sử dụng SDF như một cách để kiểm tra tính hợp lệ của ngày và mong đợi một ngày "dễ phân tích được khoan dung" (nhưng nó sẽ vượt qua). Sự khoan hồng nên là một tính năng ** thêm ** cho những người hiểu nó và ** thực sự cần phải sử dụng nó **. Thật lố bịch khi các nhà phát triển Java quyết định biến nó trở thành một hành vi tiêu chuẩn của hệ thống SDF, buộc mọi người khác phải học và sử dụng 'setLenient (false)'. Argh! ... – ADTC

+0

@ADTC: Tạo một nhà máy đặt các giá trị mặc định thích hợp cho mỗi thành phần bạn tạo. – Atmocreations

+0

"một ngoại lệ" - người ta phải thích tài liệu đó. Địa ngục, tôi muốn bắt nó, vì vậy hãy cho tôi loại. Tôi mong đợi 'set()' để ném một ngoại lệ. Thay vào đó, phương thức [getTime()] (https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getTime%28%29) ném ra một IllegalArgumentException. –

10

Nếu ngày không khoan dung, nó sẽ ném lỗi nếu bạn vượt quá phạm vi ngày nhưng nếu không thì nó sẽ chấp nhận và sửa lỗi. ví dụ: August 61st từ nhận xét ở trên sẽ trở thành ngày 30 tháng 9. Java doc về cách đặt. Mặc định là đúng.

7

Đối tượng DateFormat được khoan dung theo mặc định.

Leniency (Javadoc - Lịch)

Lịch có hai chế độ để giải thích các lĩnh vực lịch, nhân hậu và phi nhân hậu. Khi Lịch ở chế độ nhân hậu, nó chấp nhận một phạm vi rộng hơn của các giá trị trường lịch so với lịch.Khi Lịch tính lại giá trị trường lịch cho trả về bằng get(), tất cả các trường lịch đều được chuẩn hóa. Ví dụ, một nhân hậu GregorianCalendar dịch THÁNG == Tháng Một, DAY_OF_MONTH == 32 như Tháng Hai 1.

Khi Lịch đang ở chế độ không khoan dung, nó ném một ngoại lệ nếu có bất kỳ mâu thuẫn trong các lĩnh vực lịch của nó . Ví dụ: GregorianCalendar luôn tạo ra các giá trị DAY_OF_MONTH từ 1 đến độ dài của tháng. Một GregorianCalendar không khoan dung ném một ngoại lệ khi tính giá trị trường thời gian hoặc lịch của nó nếu bất kỳ giá trị trường ngoài phạm vi nào đã được đặt.

+2

@Binaya: bạn không cần phải đăng thông điệp "cảm ơn" cho mọi người đã giúp. Trong thực tế nó là * chán nản *. Đơn giản chỉ cần upvote mỗi câu trả lời đã giúp bạn (và tùy chọn chấp nhận một trong đó đã giúp nhất). Xem [FAQ] (http://stackoverflow.com/questions/how-to-answer) (phần Trả tiền chuyển tiếp). –

+2

@ Joachim Sauer, cảm ơn bạn không bao giờ chán nản. –

+0

@TheEliteGentleman: Tôi không chắc chắn rằng tôi đồng ý (nó * làm * thêm tiếng ồn), nhưng quan trọng hơn là cần lưu ý rằng tại thời điểm tôi đăng nhận xét này câu trả lời này không có upvotes (và OP có đủ đại diện để bỏ phiếu lên). –

17

Lời khuyên của tôi là luôn luôn biến mất. Tôi không thể nghĩ về một trường hợp mà bạn muốn khoan dung, và cài đặt này sẽ không bao giờ được mặc định cho các lớp như SimpleDateFormat. Khả năng xử lý dữ liệu có thể giải thích rác là các chuỗi thời gian hợp lệ và mở ra các lỗi có thể khó khăn trong việc kiểm tra. Ngoài ra, nếu bạn đang sử dụng khoan dung để chịu đựng các biến thể trong định dạng thời gian bạn sẽ bị đốt cháy. Ví dụ:

System.out.println(new SimpleDateFormat("yyyyMMdd").parse("2010-12-30")); 

sản lượng này (múi giờ của bạn có thể thay đổi):

Mon Nov 02 00:00:00 EST 2009 

kết quả vô lý này dường như là trừ một tháng ("-1"), ngày thứ hai ("2- ") của năm 2010. Tháng zeroth là tháng mười hai!

Thật không may, việc sử dụng setLenient (false) không dẫn đến việc diễn giải nghiêm ngặt mẫu. SimpleDateFormat sẽ chịu đựng rác sau các mô hình phù hợp, như đã thảo luận ở đây:

SimpleDateFormat.parse() ignores the number of characters in pattern

Ngoài ra, nó không phải là nghiêm ngặt về số lượng các nhân vật mô hình, chẳng hạn như "d" thay vì "đ":

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d"); 
sdf.setLenient(false); 
System.out.println("For 5: " + sdf.parse("2010/01/5")); 
System.out.println("For 05: " + sdf.parse("2010/01/05")); 
System.out.println("For 15: " + sdf.parse("2010/01/15")); 

Sản lượng:

For 5: Tue Jan 05 00:00:00 EST 2010 
For 05: Tue Jan 05 00:00:00 EST 2010 
For 15: Fri Jan 15 00:00:00 EST 2010 

Ngoài ra với setLenient (false) "2010/01/05" được chấp nhận với mô hình "yyyy/MM/dd". Và sự bất đồng dữ liệu bị bỏ qua, như "1999/2011" với mẫu "yyyy/yyyy" (câu trả lời là 2011).

Sử dụng SimpleDateFormat để xác thực chuỗi ngày/giờ đáng buồn là không đáng tin cậy. Nếu bạn làm theo các liên kết ở trên, bạn sẽ thấy một số giải pháp, bao gồm một phiên bản chặt chẽ của SimpleDateFormat được viết bởi tôi!

2

Khoan dung là liệu quy tắc nghiêm ngặt có được áp dụng tại số phân tích cú pháp hay không. Nếu một đối tượng DateFormat được khoan dung, nó sẽ chấp nhận ngày 32 tháng 1, 2005. Trên thực tế, nó sẽ mất tự do chuyển đổi nó sang ngày 1 tháng 2 năm 2006. Theo mặc định, một đối tượng DateFormat được khoan dung.

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

public class MainClass { 
    public static void main(String[] args) { 
    DateFormat shortDf = DateFormat.getDateInstance(DateFormat.SHORT); 

    DateFormat mediumDf = DateFormat.getDateInstance(DateFormat.MEDIUM); 
    DateFormat longDf = DateFormat.getDateInstance(DateFormat.LONG); 
    DateFormat fullDf = DateFormat.getDateInstance(DateFormat.FULL); 
    System.out.println(shortDf.format(new Date())); 
    System.out.println(mediumDf.format(new Date())); 
    System.out.println(longDf.format(new Date())); 
    System.out.println(fullDf.format(new Date())); 

    // parsing 
    try { 
     Date date = shortDf.parse("Jan 32, 2005"); 
    } catch (ParseException e) { 
    } 
    } 
} 

Và kết quả:

1/26/07 
Jan 26, 2007 
January 26, 2007 
Friday, January 26, 2007 
Các vấn đề liên quan