2012-06-13 44 views
6

Tôi cần phân tích chuỗi thời lượng, ở dạng 98d 01h 23m 45s thành mili giây.Chuỗi thời gian phân tích thành mili giây

Tôi đã hy vọng có tương đương với SimpleDateFormat cho thời lượng như thế này, nhưng tôi không thể tìm thấy bất cứ điều gì. Có ai khuyên bạn nên hoặc chống lại cố gắng sử dụng SDF cho mục đích này?

kế hoạch hiện tại của tôi là sử dụng regex để phù hợp với con số và làm điều gì đó như

Pattern p = Pattern.compile("(\\d+)"); 
Matcher m = p.matcher("98d 01h 23m 45s"); 

if (m.find()) { 
    int days = Integer.parseInt(m.group()); 
} 
// etc. for hours, minutes, seconds 

và sau đó sử dụng TimeUnit để đặt nó tất cả cùng nhau và chuyển đổi sang mili giây.

Tôi đoán câu hỏi của tôi là, điều này có vẻ như quá mức cần thiết, có thể thực hiện dễ dàng hơn không? Rất nhiều câu hỏi về ngày tháng và dấu thời gian được bật lên nhưng điều này hơi khác một chút, có thể.

+1

Cách tiếp cận của bạn có vẻ ổn cho đến nay. Cẩn thận với 'Integer.parseInt()' và các số 0 đứng đầu. Một cái gì đó như '... 08h ...' sẽ được hiểu là bát phân và không phân tích cú pháp. Loại bỏ bất kỳ số 0 hàng đầu nào. –

+0

@PhilippReichart không phải là nó an toàn theo cách tôi đang sử dụng nó ở trên, kể từ 'Integer.parseInt (" 08 ")' trả về '8'? – Craigy

+0

Có lẽ suy nghĩ của bạn về không gian hàng đầu. 'System.out.println (" Integer.parseInt ("009")); 'prints" 9 "trên máy tính của tôi.' H' không được chuyển tới 'parseInt', tuy nhiên, – Gene

Trả lời

5

Sử dụng Pattern là cách hợp lý để thực hiện. Nhưng tại sao không sử dụng một duy nhất để có được tất cả bốn lĩnh vực?

Pattern p = Pattern.compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s"); 

Sau đó, sử dụng tìm nạp nhóm được lập chỉ mục.

EDIT:

Building tắt của ý tưởng của bạn, tôi cuối cùng đã viết phương pháp sau

private static Pattern p = Pattern 
     .compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s"); 

/** 
* Parses a duration string of the form "98d 01h 23m 45s" into milliseconds. 
* 
* @throws ParseException 
*/ 
public static long parseDuration(String duration) throws ParseException { 
    Matcher m = p.matcher(duration); 

    long milliseconds = 0; 

    if (m.find() && m.groupCount() == 4) { 
     int days = Integer.parseInt(m.group(1)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(days, TimeUnit.DAYS); 
     int hours = Integer.parseInt(m.group(2)); 
     milliseconds += TimeUnit.MILLISECONDS 
       .convert(hours, TimeUnit.HOURS); 
     int minutes = Integer.parseInt(m.group(3)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(minutes, 
       TimeUnit.MINUTES); 
     int seconds = Integer.parseInt(m.group(4)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(seconds, 
       TimeUnit.SECONDS); 
    } else { 
     throw new ParseException("Cannot parse duration " + duration, 0); 
    } 

    return milliseconds; 
} 
11

Kiểm tra PeriodFormatterPeriodParser từ JodaTime library.

Bạn cũng có thể sử dụng PeriodFormatterBuilder để xây dựng một phân tích cú pháp cho chuỗi của bạn như thế này

String periodString = "98d 01h 23m 45s"; 

PeriodParser parser = new PeriodFormatterBuilder() 
    .appendDays().appendSuffix("d ") 
    .appendHours().appendSuffix("h ") 
    .appendMinutes().appendSuffix("m ") 
    .appendSeconds().appendSuffix("s ") 
    .toParser(); 

MutablePeriod period = new MutablePeriod(); 
parser.parseInto(period, periodString, 0, Locale.getDefault()); 

long millis = period.toDurationFrom(new DateTime(0)).getMillis(); 

Bây giờ, tất cả điều này (đặc biệt là phần toDurationFrom(...)) có thể trông phức tạp, nhưng tôi thực sự khuyên bạn nhìn vào JodaTime nếu bạn đang xử lý các khoảng thời gian và thời lượng trong Java.

Đồng thời xem at this answer about obtaining milliseconds from JodaTime period để biết thêm chi tiết.

+1

Cảm ơn bạn đã trả lời rất chi tiết! Thật không may tôi sẽ sử dụng giải pháp không yêu cầu thêm phụ thuộc, nhưng tôi chắc chắn ai đó sẽ sử dụng mã của bạn – Craigy

+0

Tôi có! Cảm ơn! – Tom

4

Các java.time.Duration lớp mới trong Java 8 bạn hãy phân tích khoảng thời gian ra khỏi hộp:

Duration.parse("P98DT01H23M45S").toMillis(); 

định dạng hơi khác một chút nên cần điều chỉnh trước khi phân tích cú pháp.

+0

Tôi vừa mới đăng câu hỏi SO mới để phân tích cú pháp "00:07:21.5958786 "và trả về một số nguyên (tính bằng milis hoặc bằng nanos) .Vì vậy, tài liệu đã được di chuyển nên đáng lưu ý là bạn nên sử dụng java.time.Duration, không phải các lớp Thời lượng khác. – Daniel

+0

cảm ơn, liên kết hỏng cố định – Andrejs

Các vấn đề liên quan