2009-05-31 238 views
5

從給定日期開始,我需要計算當天的午夜。這是我想出來的。我覺得這是非常難看的,必須有更好的方法。計算給定日期的日期

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(); 
} 

建議?

肯特

+3

好耶 - 第一艾倫凱,現在肯特·貝克。 SO是要去的地方... – duffymo 2009-05-31 01:32:39

+0

比這更糟的是,您發佈的代碼並未考慮您可能會或可能不在乎的時區。 – Yishai 2009-05-31 03:00:09

+0

簡單檢查一下[這裏](http://developer-dot-android.blogspot.com/2012/03/date-into-day-tutorial.html) – 2012-03-17 18:42:04

回答

7

您應該考慮內置日期API obselete。而是使用Joda日期和時間API。

下面是您的方法的替代方案。

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

這裏有一個簡單的測試:

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); 
} 

輸出是:

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

如果你正在尋找當地時間,這是最好的你會得到。儘管你可能認爲這很醜陋,但幕後還是有可能發生了很多事情。

如果你想在午夜UTC,下面的工作:

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; 
} 

編輯:我真的不推薦使用「生產」代碼當地日期。他們造成比他們的價值更多的麻煩 - 考慮一個美國西海岸的人突然發現他/她的「日子」減少了3個小時,因爲東岸計算機對午夜有不同的想法。

5

JODA可能會有更好的解決方案,但需要另外依賴庫。我正在看它的DateMidnight property。對不起,我不能更權威地回答,但我自己並不是JODA用戶。

0

我認爲讓代碼顯着更好的唯一方法是通過表示的變化。例如,

  • 代表由納徹姆·德肖維茨和Ed萊因戈爾德在Calendrical Calculations解釋了「絕對日期」制度的一天。

  • 通過從午夜開始計算秒數來表示時間。或者如果您需要亞秒級分辨率,請計算毫秒數。

從你簡單的例子,我不能告訴在你的程序是什麼點,你需要與現有的DateCalendar類兼容,或者您​​可以創建使用理智的表示一個有用的子類。

0

有段時間沒有編寫Java,但您可能可以調用此set method傳遞當前值爲年,月和日。儘管從稍微閱讀一下,但您可能必須先打電話通知。這可能會或可能不會比使用您當前的方法少冗長。

1

JODA是,去,如果你有嚴重的日曆需求至少要等到JSR-310進入的方式JDK(1.7也許,如果不是1.8)。

這就是說,有幾件事可以做,使這段代碼更好一點。

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(); 
} 

這將不會贏得任何表現獎。你可以依靠特定的字段值來做一個循環的標準(Calendar類有一個FIELD_COUNT字段類型,暗示你可以做類似的事情),但是在JDK實現和版本之間存在風險問題。

0

這只是原來發布的代碼的補充。它將Year,Month和Day設置爲新的GregorianCalendar對象,而不是清除日曆變量中除Year,Month和Day之外的所有內容。這並沒有太大的改進,但我認爲更清楚地說出你正在複製哪些字段,而不是你忽略哪些字段。

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(); 
} 

就我個人而言,我想我會去與別人提出的喬達圖書館。

1

使用date4j庫:

DateTime start = dt.getStartOfDay();