javaapache-commons-langapache-commons-dateutils

Apache DateUtils truncate for WEEK


I'm using Apache commons-lang3 DateUtils.truncate(Calendar calendar, int field) method to 'cut off' unnecessary fields of a Calendar object. Now when the field parameter gets the value of Calendar.WEEK_OF_MONTH, it throws a

java.lang.IllegalArgumentException: The field 4 is not supported

The truncate() method's documentation says:

/**
 * <p>Truncates a date, leaving the field specified as the most
 * significant field.</p>
 *
 * <p>For example, if you had the date-time of 28 Mar 2002
 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
 * 2002 13:00:00.000.  If this was passed with MONTH, it would
 * return 1 Mar 2002 0:00:00.000.</p>
 * 
 * @param date  the date to work with, not null
 * @param field  the field from {@code Calendar} or <code>SEMI_MONTH</code>
 * @return the different truncated date, not null
 * @throws IllegalArgumentException if the date is <code>null</code>
 * @throws ArithmeticException if the year is over 280 million
 */

So I assume this should work, but it clearly doesn't. Is there a way to truncate dates to the week's first day using DateUtils?


UPDATE:

I looked up in the source code and found out that the modify() method (tuncate() uses this internally), iterates through a bunch of predefined fields to find the given parameter. Now these fields are:

private static final int[][] fields = {
        {Calendar.MILLISECOND},
        {Calendar.SECOND},
        {Calendar.MINUTE},
        {Calendar.HOUR_OF_DAY, Calendar.HOUR},
        {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM 
            /* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */
        },
        {Calendar.MONTH, DateUtils.SEMI_MONTH},
        {Calendar.YEAR},
        {Calendar.ERA}};

As one can see, there is nothing related to Calendar's WEEK-ish fields, so I guess I have to do this manually... Any other thoughts/recommendations are welcome!


Solution

  • It's not really possible to truncate by a week in a sensible fashion. Consider the following date:

    2014-11-01 12:01:55
    
    2014-11-01 12:01:00 // truncate minute
    2014-11-01 00:00:00 // truncate day
    2014-11-00 00:00:00 // truncate month
    

    The original date is a Saturday. So what does week truncation mean in that case? Should we truncate to the previous Monday? If so, that would be:

    2014-10-27 00:00:00 // truncate week?
    

    That doesn't seem right to me. We've changed the month in this case; sometimes even the year would change. If you can think of a sensible way to describe this (and some use cases), please file an issue and we'll take a look at it. But it strikes me as a field that makes no sense for truncation.

    You may find some ideas for your original problem here: Retrieve current week's Monday's date