Sử dụng API Ngày & Giờ của Joda để phân tích cú pháp nhiều định dạng


76

Tôi đang phân tích cú pháp các tệp nhật ký của bên thứ ba chứa ngày / giờ bằng Joda. Ngày / giờ ở một trong hai định dạng khác nhau, tùy thuộc vào độ tuổi của tệp nhật ký mà tôi đang phân tích cú pháp.

Hiện tại tôi có mã như thế này:

try {
    return DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").parseDateTime(datePart);
} catch (IllegalArgumentException e) {
    return DateTimeFormat.forPattern("E, MMM dd, yyyy HH:mm").parseDateTime(datePart);
}

Điều này có hiệu quả nhưng trái ngược với lời khuyên của Joshua Bloch từ Phiên bản Java thứ 2 hiệu quả (Mục 57: Chỉ sử dụng ngoại lệ cho các điều kiện ngoại lệ). Nó cũng làm cho việc xác định xem IllegalArgumentException có xảy ra do ngày / giờ không đúng trong tệp nhật ký không.

Bạn có thể đề xuất một cách tiếp cận tốt hơn mà không sử dụng sai các ngoại lệ không?


Có lẽ bằng cách đoán mô hình trước khi sử dụng nó.
sly7_7

Câu trả lời:


146

Bạn có thể tạo nhiều trình phân tích cú pháp và thêm chúng vào trình tạo bằng cách sử dụng phương thức DateTimeFormatterBuilder.append :

DateTimeParser[] parsers = { 
        DateTimeFormat.forPattern( "yyyy-MM-dd HH" ).getParser(),
        DateTimeFormat.forPattern( "yyyy-MM-dd" ).getParser() };
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append( null, parsers ).toFormatter();

DateTime date1 = formatter.parseDateTime( "2010-01-01" );
DateTime date2 = formatter.parseDateTime( "2010-01-01 01" );

1
Điều này hoạt động hoàn hảo. Tôi đoán JodaStephen có ý định này, nhưng khi tôi cố gắng thực hiện mọi thứ theo hướng dẫn của anh ấy, việc phân tích cú pháp không thành công.
Steve McLeod

2
Điều này không hoạt động, chẳng hạn như '5-5-5' và '5-5-2005' nếu bạn muốn cả dd-MM-yy và dd-MM-yyyy (không thể phân tích cú pháp ngoại lệ). Sau đó, tôi phát hiện ra rằng dd-MM-yy cũng phân tích cú pháp dd-MM-yyyy rất tốt, vì vậy điều đó đã giải quyết được vấn đề của tôi.
Steven

1
Thật kỳ lạ, mặc dù có nhiều loại appendquá tải, đây là lần duy nhất không có ngoại lệ khi đưa ra các định dạng xung đột.
shmosel

17

Joda-Time hỗ trợ điều này bằng cách cho phép chỉ định nhiều trình phân tích cú pháp - DateTimeFormatterBuilder # append

Đơn giản chỉ cần tạo hai định dạng của bạn bằng cách sử dụng trình tạo và gọi toParser()mỗi định dạng . Sau đó, sử dụng trình xây dựng để kết hợp chúng bằng cách sử dụng append.


4
Ái chà! Câu trả lời trực tiếp từ chính người đàn ông! Yêu công việc của bạn Stephen.
Steve McLeod

3
Hmm, tôi đã thử điều này, nhưng Joda-Time sau đó dường như mong đợi chuỗi được phân tích cú pháp để khớp với một mẫu bao gồm CẢ HAI các mẫu được nối với nhau, thay vì một HOẶC cái kia.
Steve McLeod

Có lẽ diễn đàn này là một vị trí tốt hơn để xem nếu điều này là một lỗi - sourceforge.net/projects/joda-time/forums/forum/337835
JodaStephen

7

Thật không may, tôi không tin rằng Joda Time có bất kỳ khả năng nào như vậy. Sẽ rất tuyệt nếu có một phương thức "tryParseDateTime", nhưng nó không tồn tại.

Tôi khuyên bạn nên tách hành vi này thành lớp của riêng bạn (lớp này có danh sách các mẫu và sẽ thử lần lượt từng mẫu) để sự xấu chỉ ở một nơi. Nếu điều này gây ra các vấn đề về hiệu suất, bạn có thể muốn thử sử dụng một số phương pháp phỏng đoán để đoán định dạng nào cần thử trước. Ví dụ, trong trường hợp của bạn nếu chuỗi bắt đầu bằng một chữ số thì có thể đó là mẫu đầu tiên.

Lưu ý rằng DateTimeFormatters trong Joda Time theo quy ước là bất biến - bạn không nên tạo một cái mới mỗi khi bạn muốn phân tích cú pháp một dòng. Tạo chúng một lần và sử dụng lại.


Câu trả lời này mang lại một ý nghĩa cho nhận xét của tôi. Tôi khá hài lòng :) Tôi vẫn là một người mới bắt đầu, vì vậy tôi sẽ không từ bỏ nó như là câu trả lời
sly7_7

Cảm ơn Jon. Tôi biết về DateTimeFormatters là bất biến, nhưng vì lợi ích ngắn gọn trong ví dụ mã của tôi đã tạo chúng một cách rõ ràng. Không có vấn đề về hiệu suất không thể chấp nhận được, vì vậy tôi nghĩ tôi sẽ làm những gì bạn đề xuất và tạo một lớp học để che giấu sự xấu xí.
Steve McLeod,

Boo Java vì thiếu các chức năng TryParse như DotNet. Việc thiếu các quy trình tryParse và tính năng xóa kiểu chung chung là hai vấn đề lớn nhất của tôi. docs.oracle.com/javase/tutorial/java/generics/erasure.html
granadaCoder
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.