Java.util.Date: семь дней назад
У меня есть отчет, созданный в Jasper Reports, который ТОЛЬКО распознает java.util.Date(не календарь или григорианский и т.д.).
Есть ли способ создать дату за 7 дней до текущей даты?
В идеале это выглядит примерно так:
new Date(New Date() - 7)
UPDATE: я не могу подчеркнуть это достаточно: JasperReports НЕ ПРИЗНАЕТ объекты Java Calendar.
Ответы
Ответ 1
С этого момента:
long DAY_IN_MS = 1000 * 60 * 60 * 24;
new Date(System.currentTimeMillis() - (7 * DAY_IN_MS))
Из произвольного Date date
:
new Date(date.getTime() - (7 * DAY_IN_MS))
Изменить: Как указано в других ответах, не учитывается переход на летнее время, если это фактор.
Просто чтобы уточнить это ограничение, о котором я говорил:
Для людей, пострадавших от летнего времени, если по 7 days earlier
, вы имеете в виду, что если прямо сейчас 12pm noon on 14 Mar 2010
, вы хотите, чтобы вычисление 7 days earlier
приводило к 12pm on 7 Mar 2010
, то будьте осторожны.
Это решение находит дату/время ровно 24 часа * 7 дней = 168 часов раньше.
Однако некоторые люди удивлены, когда это решение обнаруживает, что, например, (14 Mar 2010 1:00pm) - 7 * DAY_IN_MS
может вернуть результат в (7 Mar 2010 12:00pm)
, где часовое время в вашем часовом поясе не совпадает с 2 датой/временем (1pm
vs 12pm
). Это происходит из-за перехода на летнее время, начинающегося или заканчивающегося в ту ночь, и "настенные часы" теряют или набирают час.
Если DST не является для вас фактором или если вы действительно хотите (168 hours)
точно (независимо от смены времени настенных часов), то это решение отлично работает.
В противном случае вам может потребоваться скомпенсировать, когда ваш 7 days earlier
на самом деле не означает ровно 168 часов (из-за запуска или окончания DST в течение этого таймфрейма).
Ответ 2
Используйте функцию Календаря для создания новых объектов Date с помощью getTime()
:
import java.util.GregorianCalendar;
import java.util.Date;
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysAgo = cal.getTime();
Ответ 3
попробовать
Date sevenDay = new Date(System.currentTimeMillis() - 7L * 24 * 3600 * 1000));
Другой способ - использовать Календарь, но я не люблю его использовать самостоятельно.
Ответ 4
Поскольку никто еще не упомянул TimeUnit
:
new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7))
Ответ 5
Попробуйте следующее:
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, -7);
return c.getTime();
Ответ 6
Я не уверен, когда они добавили их, но JasperReports имеет свой собственный набор "функций", которые могут манипулировать датами. Вот пример, который я не тестировал полностью:
DATE(YEAR(TODAY()), MONTH(TODAY()), DAY(TODAY()) - 7)
Создает java.util.Date
с датой, установленной до 7 дней с сегодняшнего дня. Если вы хотите использовать другую дату "привязки", просто замените TODAY()
на любую дату, которую вы хотите использовать.
Ответ 7
Для определения "дней" требуется часовой пояс. Часовой пояс определяет, когда начинается "день". Часовой пояс включает правила обработки летнего времени и другие аномалии. Нет волшебства, чтобы сделать часовые пояса неактуальными. Если вы проигнорируете проблему, будет применяться часовой пояс JVM по умолчанию. Это ведет к путанице и боли.
Избежать java.util.Date
Классы java.util.Date и .Calendar, как известно, хлопотны. Избежать их. Они настолько плохи, что Sun/Oracle согласились вытеснить их с помощью нового пакета java.time на Java 8. Используйте либо это, либо Joda-Time.
Joda времени
Пример кода в Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); // Specify or else the JVM default will apply.
DateTime dateTime = new DateTime( new java.util.Date(), timeZone ); // Simulate passing a Date.
DateTime weekAgo = dateTime.minusDays( 7 );
Первый момент дня
Или вы можете настроить время суток в первый момент дня, чтобы зафиксировать весь день. Вызвать метод withTimeAtStartOfDay
. Имейте в виду, что это обычно 00:00:00
, но не всегда.
Избегайте методов и классов "полночь" в Joda-Time. Они основаны на ошибочной концепции и теперь устарели.
DateTime dateTimeStart = new DateTime( new java.util.Date(), timeZone ).withTimeAtStartOfDay(); // Not necessarily the time "00:00:00".
DateTime weekAgo = dateTime.minusDays( 7 ).withTimeAtStartOfDay();
Преобразовать в/из j.u.Date
Как видно выше, конвертировать из java.util.Date в Joda-Time просто передать объект Date в конструктор DateTime. Поймите, что j.u.Date не имеет часового пояса, DateTime делает. Поэтому назначьте желаемый/соответствующий часовой пояс для определения того, какие "дни" и когда они начинаются.
Чтобы перейти в другую сторону, DateTime в j.u.Date, просто вызовите метод toDate
.
java.util.Date date = dateTime.toDate();
Ответ 8
Есть ли причина, по которой вы не можете сделать расчет в своей поддержке bean? Затем отправьте его в свой отчет в качестве параметра.
Ответ 9
Из-за жаркого обсуждения:
Вопрос может не иметь правильного ответа без определенного часового пояса.
ниже это некоторый код для работы с стандартным (и, следовательно, устаревшим) часовым поясом, который учитывает переход на летнее время по умолчанию.
Date date= new Date();
date.setDate(date.getDate()-7);//date works as calendar w/ negatives
В то время как решение действительно работает, оно точно так же фиктивно, как и в случае принятия часового пояса.
new Date(System.currentTimeMillis() - 10080*60000);//a week has 10080 minutes
Пожалуйста, не голосуйте за ответ.
Ответ 10
Я делаю так:
Date oneWeekAgo = DateUtils.addDays(DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH), -7);
Ответ 11
Вы можете попробовать это,
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, -7);
System.out.println(new java.sql.Date(c.getTimeInMillis()));
Ответ 12
Решение на основе Java 8:
new Date(Instant.now().minus(7, ChronoUnit.DAYS).toEpochMilli()))