2010-02-14 124 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