5

我正在使用Apache commons-lang3 DateUtils.truncate(Calendar calendar, int field)方法来“切断”日历对象的不必要字段。现在,当field参数获取 的值时Calendar.WEEK_OF_MONTH,它会抛出一个

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

truncate()方法的文档说:

/**
 * <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
 */

所以我认为这应该可行,但显然不行。有没有办法使用 DateUtils 将日期截断为一周的第一天?


更新

我在源代码中查找并发现该modify()方法(tuncate()在内部使用 this)遍历了一堆预定义的字段以找到给定的参数。现在这些字段是:

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}};

正如人们所看到的,与CalendarWEEK 的字段没有任何关系,所以我想我必须手动执行此操作......欢迎任何其他想法/建议!

4

2 回答 2

3

以合理的方式将其截断一周是不可能的。考虑以下日期:

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

原来的日期是星期六。那么在这种情况下,周截断意味着什么?我们应该截断到前一个星期一吗?如果是这样,那将是:

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

这对我来说似乎不对。在这种情况下,我们更改了月份;有时甚至年份都会改变。如果您能想到一种合理的方式来描述这一点(以及一些用例),请提出问题,我们将对其进行研究。但它给我的印象是一个对截断毫无意义的领域。

您可能会在此处找到解决原始问题的一些想法:检索本周的星期一日期

于 2014-10-31T19:58:36.813 回答
3

tl;博士

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

java.time

不需要像DateUtils. 使用 Java 8 及更高版本中内置的 java.time 类。

听起来您真正的问题是如何获得特定日期的一周的第一天。

时区

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,法国巴黎午夜过后几分钟是新的一天,而魁北克蒙特利尔仍然是“昨天” 。

以、或等格式指定适当的时区名称。永远不要使用 3-4 个字母的伪时区,例如它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

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

该类LocalDate表示没有时间和时区的仅日期值。

LocalDate today = LocalDate.now( z );

要获取该日期的一周的第一天,我们必须定义一周的第一天。该定义因文化而异。在美国,我们通常指的是星期日。世界其他大部分地区意味着星期一。对于您的用户来说,使用DayOfWeek枚举对象指定。

要从我们的日期移动到那个日期,请使用类中的TemporalAdjuster实现TemporalAdjusters

LocalDate firstOfWeek = today.with( 
    TemporalAdjuster.previousOrSame​( DayOfWeek.MONDAY ) 
) ;
于 2017-12-29T04:54:17.317 回答