Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 264
Sleeper9 Avatar asked Oct 31 '14 10:10

Sleeper9


People also ask

What does DateUtils truncate do?

MONTH field, DateUtils. truncate( ) will return a Date object set to the first instance of the month. The day, hour, minute, second, and millisecond field will each contain the minimum possible value for that field.

What is DateUtils in java?

A suite of utilities surrounding the use of the Calendar and Date object. DateUtils contains a lot of common methods considering manipulations of Dates or Calendars. Some methods require some extra explanation. The truncate, ceiling and round methods could be considered the Math.


2 Answers

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

like image 74
Duncan Jones Avatar answered Oct 11 '22 20:10

Duncan Jones


tl;dr

LocalDate.now( 
    ZoneId.of( "Africa/Tunis" )
).with( 
    TemporalAdjuster.previousOrSame​( DayOfWeek.MONDAY )
)

java.time

No need for an external library like DateUtils. Use the java.time classes built into Java 8 and later.

Sounds like your real question is how to get the first day of the week for a particular date.

Time zone

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;

The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate today = LocalDate.now( z );

To get the first day of the week for that date, we must define the first day of the week. That definition varies by culture. In the United States, we usually mean Sunday. Much of the rest of the world means Monday. Which ever it is for your users, specify with a DayOfWeek enum object.

To move from our date to that date, use a TemporalAdjuster implementation found in TemporalAdjusters class.

LocalDate firstOfWeek = today.with( 
    TemporalAdjuster.previousOrSame​( DayOfWeek.MONDAY ) 
) ;
like image 39
Basil Bourque Avatar answered Oct 11 '22 21:10

Basil Bourque