2010-02-14 123 views
26

我的API允許庫客戶端傳遞日期:在喬達時間,設置日期時間開始一個月

method(java.util.Date date) 

Joda-Time工作,從這個日期,我想所有的日子提取月份和遍歷這個月包含。

現在,通過日期通常是新日期() - 意思是當前時刻。我的問題實際上是將新的DateMidnight(jdkDate)實例設置爲月初。

有人可以用Joda-Time來演示這個用例嗎?

+0

問題標題應該提及喬達時間。 – 2010-02-14 15:38:07

+0

它確實「有人可以用喬達時間來證明這個用例。」我已經添加了另一個註釋來更清楚地表明這是一個焦急時間問題。 – 2010-02-14 16:08:32

+0

@MaximVeksler Lachlan Roche表示*標題*應該提及Joda-Time。我做了編輯。 – 2013-11-25 23:35:00

回答

41

午夜在當月的第一天開始由下式給出:

// first midnight in this month 
DateMidnight first = new DateMidnight().withDayOfMonth(1); 

// last midnight in this month 
DateMidnight last = first.plusMonths(1).minusDays(1); 

如果從java.util.Date開始,不同的DateMidnight構造函數用於:

// first midnight in java.util.Date's month 
DateMidnight first = new DateMidnight(date).withDayOfMonth(1); 

Joda Time java doc - http://joda-time.sourceforge.net/api-release/index.html

+0

順便說一下,在「最後」爲什麼不是: DateMidnight last = first.plusMonths(1).minusDays(1);同樣的事情,只是更乾淨。 – 2010-02-14 16:19:12

+1

這個答案是正確的,但現在過時了。不是每個時區都有午夜。 Joda-Time 2添加了一個方法['withTimeAtStartOfDay'](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#withTimeAtStartOfDay())來代替「午夜「 特徵。 – 2013-11-25 23:31:06

+0

DateMidnight現已棄用。來自JavaDoc:「在某些時區夏令時並不存在,夏令時向前轉換跳過了午夜時間。使用LocalDate表示沒有時區的日期,或者使用DateTime來表示一個完整的日期和時間,或許使用DateTime.withTimeAtStartOfDay()在一天的開始瞬間獲得。「 – JustinKSU 2014-10-09 21:08:46

5

哦,我沒有看到這是關於喬達泰時代。總之:

Calendar c = Calendar.getInstance(); 
c.setTime(date); 
c.set(Calendar.HOUR_OF_DAY, 0); 
c.set(Calendar.MINUTE, 0); 
c.set(Calendar.SECOND, 0); 
c.set(Calendar.MILLISECOND, 0); 

int min = c.getActualMinimum(Calendar.DAY_OF_MONTH); 
int max = c.getActualMaximum(Calendar.DAY_OF_MONTH); 
for (int i = min; i <= max; i++) { 
    c.set(Calendar.DAY_OF_MONTH, i); 
    System.out.println(c.getTime()); 
} 

或者使用公地郎鹹平:

Date min = DateUtils.truncate(date, Calendar.MONTH); 
Date max = DateUtils.addMonths(min, 1); 
for (Date cur = min; cur.before(max); cur = DateUtils.addDays(cur, 1)) { 
    System.out.println(cur); 
} 

+0

感謝您的java基本API說明。我也從中學到了。 – 2010-02-14 16:11:17

+0

+1對於commons-lang示例,這很方便 – Peter 2012-05-22 18:26:42

28

的另一種方式(不考慮DateMidnight考慮),以獲得該月的第一天是使用:

DateTime firstDayOfMonth = new DateTime().dayOfMonth().withMinimumValue(); 
+5

joda時間很棒 – tbruyelle 2011-12-27 13:29:24

+5

儘管日期將是本月的第一天,但​​時間仍將在一天中。將.withTimeAtStartOfDay()添加到最後可以解決此問題。 – JustinKSU 2014-10-09 21:05:41

+0

您還可以添加.dayOfMonth()。withMaximumValue()。hourOfDay()。withMaximumValue()並且可以添加相同的小時數分鐘...以更加精確 – 2017-10-18 13:35:49

7

當天的第一瞬間

answer by ngeek是正確的,但沒有把時間放在一天的第一時刻。要調整時間,請撥打withTimeAtStartOfDay

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. 

org.joda.time.DateTime startOfThisMonth = new org.joda.time.DateTime().dayOfMonth().withMinimumValue().withTimeAtStartOfDay(); 
org.joda.time.DateTime startofNextMonth = startOfThisMonth.plusMonths(1).dayOfMonth().withMinimumValue().withTimeAtStartOfDay(); 

System.out.println("startOfThisMonth: " + startOfThisMonth); 
System.out.println("startofNextMonth: " + startofNextMonth); 

當在美國西雅圖的運行...

startOfThisMonth: 2013-11-01T00:00:00.000-07:00 
startofNextMonth: 2013-12-01T00:00:00.000-08:00 

注意在控制檯輸出的這兩條線的區別:-7 VS -8因爲Daylight Saving Time


通常,應該總是指定時區而不是依賴於默認值。這裏爲簡單起見省略。應該像這樣添加一行,並將時區對象傳遞給上面示例中使用的構造函數。

// Time Zone list: http://joda-time.sourceforge.net/timezones.html (Possibly out-dated, read note on that page) 
// UTC time zone (no offset) has a constant, so no need to construct: org.joda.time.DateTimeZone.UTC 
org.joda.time.DateTimeZone kolkataTimeZone = org.joda.time.DateTimeZone.forID("Asia/Kolkata"); 

java.time

以上是正確的,但已經過時。 Joda-Time庫現在被Java 8及更高版本中內置的java.time框架所取代。

LocalDate表示沒有時間和沒有時區的只有日期的值。時區對確定日期至關重要。對於任何特定時刻,日期因地區而異。

ZoneId zoneId = ZoneId.of("America/Montreal"); 
LocalDate today = LocalDate.now(zoneId); 

使用TemporalAdjusters之一來獲得月的第一個月。

LocalDate firstOfMonth = today.with(TemporalAdjusters.firstDayOfMonth()); 

LocalDate可以產生ZonedDateTime表示當天的第一時刻。

ZonedDateTime firstMomentOfCurrentMonth = firstOfMonth.atStartOfDay(zoneId); 
-1

DateMidnight現已棄用。相反,你可以這樣做:

LocalDate firstOfMonth = new LocalDate(date).withDayOfMonth(1); 
LocalDate lastOfMonth = firstOfMonth.plusMonths(1).minusDays(1); 

如果你知道的時區使用new LocalDate(date, timeZone),而不是獲得更高的精度。

你也可以做的,而不是.dayOfMonth().withMinimumValue().withDayOfMonth(1)

編輯:

這會給你12/1/YYYY 00:0012/31/YYYY 00:00。如果你寧願在本月的最後一個月實際上是下個月的第一天(因爲你正在做一個between子句),那麼從lastOfMonth計算中刪除minusDays(1)

+0

這對於lastOfMonth是不正確的。 – 2015-01-17 10:28:11

+0

@Xylian我想這取決於問題的解釋。對於任何一天,它會在本月的最後一個月的第一天和午夜給你午夜。如果你想要在下個月第一天的午夜,只需從第二天刪除「.minusDays(1)。如果你仍然認爲我的回答不正確,請詳細說明,因爲我的單元測試表明它的工作原理。 – JustinKSU 2015-01-19 16:47:35