45

I have never used JodaTime before, but answering this question, How to get ordinal Weekdays in a Month.

I tried it and came up with this ugly code to unset all fields below day:

DateTime startOfMonth =
    input.withDayOfMonth(1)
        .withHourOfDay(0)       // there
        .withMinuteOfHour(0)    // has got to
        .withSecondOfMinute(0)  // be a shorter way
        .withMillisOfSecond(0); // to do this

Where the Commons / Lang equivalent using DateUtils would be

Date startOfMonth = DateUtils.truncate(input, Calendar.MONTH);

What's the preferred idiom to do that in JodaTime?

Community
  • 1
  • 1
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588

4 Answers4

46

You can use roundFloorCopy() to mimic DateUtils.truncate

Date truncateMonth = DateUtils.truncate(input, Calendar.MONTH);
-> DateTime truncateMonth = input.dayOfMonth().roundFloorCopy();

Date truncateMinute = DateUtils.truncate(input, Calendar.MINUTE);
-> DateTime truncateMinute = input.minuteOfDay().roundFloorCopy();

Date truncateHourOfDay = DateUtils.truncate(input, Calendar.HOUR_OF_DAY);
-> DateTime truncateHourOfDay = input.hourOfDay().roundFloorCopy()
JodaStephen
  • 60,927
  • 15
  • 95
  • 117
Soundlink
  • 3,915
  • 2
  • 28
  • 36
  • 1
    By far the best in my opinion. I needed the date to be "rounded" by something selected by the user. Using [code]input.property().roundFloorCopy()[/code] saved a lot of custom coding. – Andrew Wynham May 13 '13 at 16:24
42

Use the withMillisOfDay() method to shorten the syntax.

DateTime startOfMonth = input.withDayOfMonth(1).withMillisOfDay(0);
Erick Robertson
  • 32,125
  • 13
  • 69
  • 98
  • Bozho's answer is probably the "official" solution, but I like this one better. Thanks. – Sean Patrick Floyd Nov 09 '10 at 12:52
  • Why would you think that? I don't get it. I like this one better too, because it requires the minimum number of objects to be created. – Erick Robertson Nov 09 '10 at 13:06
  • Why would I think that? Because a dedicated class exists for this exact kind of problem. – Sean Patrick Floyd Nov 09 '10 at 16:09
  • 3
    I would say that the `withMillisOfDay` method exists for this exact kind of problem. The `DateMidnight` class exists for some other kind of problem, where you want to keep references to those objects around. It's silly to use another class just to have to convert it back immediately -- especially when the class you were working with has a method that does exactly what you're looking for. – Erick Robertson Nov 09 '10 at 17:18
  • both answers each construct the same number of objects – Kirby Apr 21 '16 at 17:28
21

Take a look at DateMidnight.

DateTime startOfMonth = new DateTime(new DateMidnight(input.withDayOfMonth(1)));

Update: 2013-08-16 by JodaStephen: Version 2.3 of Joda-Time deprecates DateMidnight as it was a very bad idea of a class.

So use:

DateTime startOfMonth = input.withDayOfMonth(1).withTimeAtStartOfDay();
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • so I guess you mean this: `new DateMidnight(new DateTime())` – Sean Patrick Floyd Nov 09 '10 at 12:49
  • 1
    @Erick true, but IMHO not a reason for a downvote. This is still a good answer – Sean Patrick Floyd Nov 09 '10 at 12:53
  • 2
    I don't understand why this is a better answer than using `withMillisOfDay(0)`. A `DateMidnight` object is not a `DateTime` object, so an extra object needs to be created this way. – Erick Robertson Nov 09 '10 at 13:04
  • 2
    DateMidnight should be avoided, as it has dodgy semantics (not all locations have midnight on DST change days). Use LocalDate instead of DateMidnight. The intended mechanism for this in Joda-Time is roundFloorCopy(), Soundlinks answer. – JodaStephen Sep 13 '12 at 12:47
1

Joda Time also supports the withFields method in the DateTime type. This can also be used to create a short syntax:

new DateTime().withDayOfMonth(1).withFields(new LocalTime(0, 0));

In production code the argument to withFields should be factored out to a constant.

SpaceTrucker
  • 13,377
  • 6
  • 60
  • 99