Усечение Apache DateUtils для WEEK
Я использую Apache commons-lang3 DateUtils.truncate(Calendar calendar, int field)
способ "обрезать" ненужные поля объекта Calendar. Теперь, когда 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()
использует это внутренне), перебирает кучу предопределенных полей, чтобы найти данный параметр. Теперь эти поля:
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}};
Как видите, ничего общего с Calendar
поля WEEK-ish, так что я думаю, что я должен сделать это вручную... Любые другие мысли / рекомендации приветствуются!
2 ответа
На самом деле невозможно урезать на неделю разумным способом. Рассмотрим следующую дату:
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?
Это не кажется мне правильным. Мы изменили месяц в этом случае; иногда даже год меняется. Если вы можете придумать разумный способ описать это (и некоторые варианты использования), пожалуйста, сообщите о проблеме, и мы рассмотрим ее. Но это кажется мне областью, которая не имеет смысла для усечения.
Вы можете найти некоторые идеи для вашей первоначальной проблемы здесь: Получить дату текущей недели в понедельник
ТЛ; др
LocalDate.now(
ZoneId.of( "Africa/Tunis" )
).with(
TemporalAdjuster.previousOrSame( DayOfWeek.MONDAY )
)
java.time
Нет необходимости во внешней библиотеке, такой как DateUtils
, Используйте классы java.time, встроенные в Java 8 и более поздние версии.
Похоже, ваш реальный вопрос в том, как получить первый день недели для конкретной даты.
Часовой пояс
Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а в Монреале-Квебеке все еще "вчера".
Укажите правильное название часового пояса в формате continent/region
, такие как America/Montreal
, Africa/Casablanca
, или же Pacific/Auckland
, Никогда не используйте 3-4-буквенные псевдозоны, такие как EST
или же IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate
класс представляет значение только для даты без времени суток и без часового пояса.
LocalDate today = LocalDate.now( z );
Чтобы получить первый день недели для этой даты, мы должны определить первый день недели. Это определение зависит от культуры. В Соединенных Штатах мы обычно имеем в виду воскресенье. Значительная часть остального мира означает понедельник. Что когда-либо для ваших пользователей, укажите с DayOfWeek
Перечислить объект.
Чтобы перейти от нашей даты к этой дате, используйте TemporalAdjuster
реализация найдена в TemporalAdjusters
учебный класс.
LocalDate firstOfWeek = today.with(
TemporalAdjuster.previousOrSame( DayOfWeek.MONDAY )
) ;