2009-05-31 23 views
5

Từ một ngày nhất định mà tôi cần tính nửa đêm của ngày đó. Đây là những gì tôi nghĩ ra. Thật xấu xí đến mức tôi nghĩ phải có cách tốt hơn.Tính toán một ngày được đưa ra một Ngày

private Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 0); 
    calendar.set(Calendar.SECOND, 0); 
    calendar.set(Calendar.MILLISECOND, 0); 
    return calendar.getTime(); 
} 

Đề xuất?

Kent

+3

Tốt Chúa - đầu tiên Alan Kay, bây giờ Kent Beck. SO là nơi để ... – duffymo

+0

Tệ hơn thế, mã bạn đăng không tính đến múi giờ mà bạn có thể hoặc không quan tâm. – Yishai

+0

kiểm tra đơn giản điều này [tại đây] (http://developer-dot-android.blogspot.com/2012/03/date-into-day-tutorial.html) –

Trả lời

7

Bạn nên xem xét API ngày tháng được tạo sẵn. Thay vào đó hãy sử dụng API ngày và giờ Joda.

Đây là phương án thay thế cho phương thức của bạn.

private Date day(Date creation) { 
    return new DateMidnight(creation).toDate(); 
} 

Dưới đây là một thử nghiệm đơn giản:

public static void main(String[] args) { 
    final Date creation = new Date(); 
    final Date midnight = new Foobar().day(creation); 
    System.out.println("creation = " + creation); 
    System.out.println("midnight = " + midnight); 
} 

Đầu ra là:

creation = Sun May 31 10:09:38 CEST 2009  
midnight = Sun May 31 00:00:00 CEST 2009 
2

Nếu bạn đang tìm kiếm giờ địa phương, đó là điều tốt nhất bạn sẽ nhận được. Và mặc dù bạn có thể xem xét nó xấu xí, có (có khả năng) rất nhiều đang diễn ra đằng sau hậu trường.

Nếu bạn muốn nửa đêm UTC, sau đây sẽ làm việc:

public static void main(String[] argv) 
throws Exception 
{ 
    final long MILLIS_PER_DAY = 24 * 3600 * 1000L; 

    long midnightUTC = (System.currentTimeMillis()/MILLIS_PER_DAY) * MILLIS_PER_DAY; 
} 

Sửa: Tôi thực sự không khuyên bạn nên sử dụng ngày địa phương trong việc "sản xuất" mã. Chúng gây ra nhiều rắc rối hơn chúng đáng giá - hãy xem xét một người trên bờ biển phía tây Hoa Kỳ, người đột nhiên thấy "ngày" của mình bị cắt bớt 3 giờ vì máy tính bờ biển phía đông có ý tưởng khác nửa đêm.

5

JODA có thể có giải pháp tốt hơn, với chi phí phụ thuộc khác vào thư viện. Tôi đang xem số DateMidnight property của nó. Tôi xin lỗi vì tôi không thể trả lời nhiều hơn về tác giả, nhưng tôi không phải là người dùng JODA.

0

Tôi nghĩ cách duy nhất bạn sẽ làm cho mã này tốt hơn đáng kể là thay đổi biểu diễn. Ví dụ,

  • Đại diện cho ngày bởi hệ thống "ngày tuyệt đối" giải thích bằng Nachum Dershowitz và Ed Reingold trong Calendrical Calculations.

  • Trình bày thời gian bằng cách tính giây từ nửa đêm. Hoặc nếu bạn cần độ phân giải phụ, hãy tính mili giây.

Từ ví dụ ngắn gọn của bạn tôi không thể nói những gì điểm trong chương trình của bạn, bạn cần phải tương thích với hiện DateCalendar lớp, hoặc nếu bạn có thể tạo một lớp con hữu ích sử dụng một đại diện saner.

0

Đã không lập trình Java trong một thời gian, nhưng bạn có thể gọi số này set method chuyển các giá trị hiện tại cho năm, tháng và ngày. Mặc dù từ đọc gần một chút, bạn có thể phải gọi rõ ràng trước. Điều này có thể hoặc không thể tiết lộ ít hơn so với sử dụng phương pháp hiện tại của bạn.

1

JODA là con đường để đi nếu bạn có nhu cầu lịch nghiêm trọng, ít nhất là cho đến khi JSR-310 được vào JDK (1,7 có thể, nếu không phải là 1,8).

Điều đó đang được nói, có một vài điều có thể được thực hiện để làm cho mã này đẹp hơn một chút.

import static java.util.Calendar.*; 

... 

private static final List<Integer> TIME_FIELDS = 
    Arrays.asList(HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND); 

private Date day(Date creation) { 
    Calendar c = getInstance(); 
    c.setTime(creation); 
    for(int field : TIME_FIELDS) c.set(field, 0); 
    return c.getTime(); 
} 

Điều đó sẽ không giành được bất kỳ giải thưởng hiệu suất nào. Bạn có thể làm tiêu chuẩn cho vòng lặp dựa trên các giá trị trường cụ thể (lớp Lịch có trường FIELD_COUNT ngụ ý bạn có thể làm điều gì đó tương tự) nhưng điều đó có thể gây ra các vấn đề trong quá trình triển khai JDK và giữa các phiên bản.

0

Đây chỉ là phần bổ sung của mã được đăng ban đầu. Nó đặt Năm, Tháng và Ngày trong đối tượng GregorianCalendar mới, thay vì xóa tất cả mọi thứ trừ Năm, Tháng và Ngày trong biến lịch. Nó không có nhiều cải tiến, nhưng tôi nghĩ rõ ràng hơn khi nói bạn đang sao chép trường nào, thay vì bạn bỏ qua trường nào.

public Date day(Date creation) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.setTime(creation); 
    return new GregorianCalendar(
      calendar.get(Calendar.YEAR), 
      calendar.get(Calendar.MONTH), 
      calendar.get(Calendar.DAY_OF_MONTH)).getTime(); 
} 

Cá nhân, tôi nghĩ tôi nên đi với thư viện Joda do người khác đề xuất.

1

Sử dụng date4j thư viện:

DateTime start = dt.getStartOfDay(); 
Các vấn đề liên quan