2013-02-21 52 views
7

Tôi có một thời gian tem kiểu String và tôi đang cố gắng để chuyển nó sang một đôi (và tìm ra kết quả tính bằng giây) và đây là những gì tôi đã làm:Tại sao SimpleDateFormat.parse(). GetTime() trả về giá trị sai (âm)?

double mytimeStamp = 0; 

String timeStamp = new SimpleDateFormat(" mm ss S").format(new Date()); 

SimpleDateFormat dateFormat = new SimpleDateFormat(" mm ss S"); 

try { 
    mytimeStamp = ((double)dateFormat.parse(timeStamp).getTime())/1000; 
} catch (ParseException e1) { 
    // TODO Auto-generated catch block 
    e1.printStackTrace(); 
} 

System.out.println("timeStamp is: "+ mytimeStamp); 

Vấn đề là tôi có được một giá trị như -2722.515 và tôi không biết tại sao.

Tại sao nó âm?

Có vấn đề gì với mã không?

Khi tôi chuyển đổi dấu thời gian này thành mm ss S không khớp với thời gian thực và điều này có vẻ là một vấn đề khác!

Trả lời

11

Đó là vấn đề khác biệt về múi giờ.

Vì bạn chỉ chỉ định phút và giây, ngày sẽ là 1 Jan 1970 00:mm:ss (mmss là phút và giây của thời gian hiện tại).

tôi đơn giản hóa ví dụ của bạn để:

String timeStamp = "00 00 00"; 
SimpleDateFormat dateFormat = new SimpleDateFormat("HH mm ss"); 
double hour = dateFormat.parse(timeStamp).getTime()/1000.0/60/60; 
System.out.println("hour is: "+ hour); 

Giờ in ra nên GMT 's bù đắp từ các múi giờ địa phương.

Lý do cho điều này là:

SimpleDateFormat là miền địa phương nhạy cảm, vì vậy dateFormat.parse(timeStamp) sẽ trở lại tạo ra một đối tượng Date cho một múi giờ nhất định (mặc định là múi giờ địa phương). Sau đó, getTime() lấy số mili giây từ midnight 1 Jan 1970 **GMT**. Vì vậy, giá trị sẽ được bù đắp theo khoảng thời gian địa phương từ GMT.

Làm thế nào để sửa chữa nó:

Bạn có thể sửa chữa nó bằng cách thiết lập múi giờ của đối tượng dateFormat trước parse được gọi như sau:

dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
+0

đó là có lẽ lớp SimpleTimeFormat đang cố gắng tôn vinh cài đặt múi giờ hiện tại, sẽ yêu cầu dịch thời gian thành thứ gì đó trước '1 Jan 1970 00: mm: ss'. Vì kỷ nguyên sẽ là "sau" thời gian (và có một diễn viên đôi trong đó cũng không giúp được) nó có thể trôi dạt vào một phạm vi nhỏ các giá trị nội bộ không hợp lệ, dẫn đến các giá trị bên ngoài không hợp lệ. Bạn có thể gọi nó là một lỗi, nhưng thật khó để giữ nó chịu trách nhiệm về thời gian bên ngoài của nó được tuyên bố phạm vi hiệu quả. –

+0

@EdwinBuck Đã chỉnh sửa. – Dukeling

+0

Cảm ơn bạn rất nhiều Dukeling :) nó hoạt động hoàn hảo ngay bây giờ ... – user2052015

1

--- Trên thực tế có một tốt hơn nhiều cách để thực hiện việc này, nhưng nếu bạn muốn sử dụng ngày, hãy bỏ qua đến câu trả lời trước khi chỉnh sửa ---

Ngày thực sự không thực hiện những gì bạn muốn, dường như là các phép tính thời gian bên ngoài một ctual cần phải chọn lần tắt một lịch thế giới thực.

Bạn sẽ tốt hơn nhiều khi viết lớp học của riêng mình, để tránh tất cả các xử lý đặc biệt khó chịu mà Ngày phải làm để theo kịp với Lịch Gregorian. xử lý đặc biệt này bao gồm (nhưng không giới hạn) nhận thức múi giờ, tiết kiệm ánh sáng ban ngày, tuyên bố "ngày bỏ qua", nhảy giây, năm nhuận, vv

public TimeOnly { 

    private long timestamp; 
    private int millis; 
    private int seconds; 
    ... etc ... 

    public TimeOnly(int hours, int minutes, int seconds, int millis) { 
    this.timestamp = millis + seconds * 1000L + minutes * 60000L + hours * 3600000L; 
    this.millis = millis; 
    this.seconds = seconds; 
    ... etc ... 
    } 

    private TimeOnly(long timestamp) { 
    this.timestamp = timestamp; 
    this.millis = timestamp % 1000; 
    this.seconds = timestamp % 60000L - this.millis; 
    ... etc ... 
    } 

    public long getTimestamp() { 
    return timestamp; 
    } 

    public int getMillis() { 
    return millis; 
    } 

    public int getSeconds() { 
    return seconds; 
    } 

    ... etc ... 
} 

public TimeFormatter { 

    public TimeFormatter() { 

    } 

    public String format(Time time) { 
    StringBuilder builder = new StringBuilder(); 
    builder.append(String.valueOf(time.getHours())); 
    builder.append(":"); 
    builder.append(String.valueOf(time.getMinutes())); 
    builder.append(":"); 
    builder.append(String.valueOf(time.getSeconds())); 
    builder.append("."); 
    if (time.getMillis() < 10) { 
     builder.append("00"); 
    } else if (time.getMillis() < 100) { 
     builder.append("0"); 
    } 
    builder.append(time.getMillis()); 
    return builder.toString(); 
} 

Giải pháp này có vẻ như nó được reinventing the wheel, nhưng thực sự nó là tránh việc sử dụng một hình bát giác như một bánh xe. Hành vi của ngày dường như không phải là những gì bạn muốn, mặc dù bạn có thể có thể làm cho ngày làm việc cho một số phạm vi hạn chế các giá trị.

Nếu bạn muốn thực sự ưa thích, bạn có thể làm cho việc thực hiện ở trên có thể so sánh được, v.v. Tuy nhiên, tôi khuyên bạn không nên làm gì. Không cung cấp phương thức cập nhật sau khi xây dựng, vì điều này buộc một số tính toán lại khá khó chịu và làm cho mã khó duy trì hơn. Thay vào đó, hãy cung cấp các phương thức trả về TimeOnlys mới để đáp ứng với các hoạt động mà bạn muốn thực hiện.

public TimeOnly addSeconds(int value) { 
    int stamp = this.timestamp; 
    stamp += value * 60000L; 
    if (stamp < timestamp) { 
    throw new Excepton("overflow"); 
    } 
    return new TimeOnly(stamp); 
} 

Ngoài ra, không triển khai những gì bạn sẽ không sử dụng. Mã không sử dụng có xu hướng là đất màu mỡ cho các lỗi.

Và tất nhiên, câu trả lời cho mọi thứ "thời gian", hãy cân nhắc sử dụng JodaTime, điều này phân biệt tất cả các loại đo thời gian khác nhau. Tuy nhiên, đối với một vấn đề nhỏ như thế này, nó giống như sử dụng một chiếc xe tăng để giết một con kiến.

--- Các chỉnh sửa trước câu trả lời ---

Nếu không có một đặc điểm kỹ thuật đầy đủ thời gian (năm, tháng, ngày, giờ, phút, giây, mili giây) giá trị thời gian của bạn như được định dạng trong bước đầu tiên sẽ có nhiều trường không được chỉ định. Những gì xảy ra trong các lĩnh vực đó có thể sẽ là rác.

Sau đó, getTime() hành động trên toàn bộ đối tượng Date dịch cả trường hợp lệ và rác thành giá trị, trong đó rác thậm chí có thể sửa đổi các giá trị hợp lệ (96 giây = 1 phút và 36 giây, khi các trường tương tác).

Cách tốt nhất để thực hiện điều này là có tất cả các ngày "chỉ có thời gian" được khởi tạo cho một ngày đã biết, vì vậy khi bạn so sánh và thực hiện phép toán (là, 3 11 23>1 02 10?) Bạn sẽ nhận được kết quả nhất quán (có, 3 11 23>1 02 10, bởi vì nó thực sự là 2013 02 10 00 03 11 23>2013 02 10 00 03 11 23 và không 2013 02 10 00 03 11 23 so với 2000 02 10 00 03 11 23

Khi lựa chọn ngày để sử dụng, tránh ngày tiếp giáp với 29 tháng 2, ngày có gần thay đổi tiết kiệm ánh sáng ban ngày, vv

+0

Khi tôi làm điều đó như bạn nói sau đó tôi nhận được kết quả như 1.207806075005E9 nhưng những gì tôi cần là tìm nó trong vài giây và sau đó trừ từ dấu thời gian trước đó và do đó tôi có thể tìm thấy thời lượng thoại. – user2052015

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