Как вычесть X дней из даты, используя календарь Java?
Кто-нибудь знает простой способ использовать календарь Java, чтобы вычесть X дней из даты?
Я не смог найти ни одной функции, которая позволяла бы мне напрямую вычитать X дней из даты в Java. Может ли кто-нибудь указать мне правильное направление?
11 ответов
Взято из документации здесь:
Добавляет или вычитает указанное количество времени к заданному календарному полю, основываясь на правилах календаря. Например, чтобы вычесть 5 дней из текущего времени календаря, вы можете добиться этого, позвонив:
Calendar calendar = Calendar.getInstance(); // this would default to now calendar.add(Calendar.DAY_OF_MONTH, -5).
Вы могли бы использовать add
метод и передать ему отрицательное число. Тем не менее, вы также можете написать более простой метод, который не использует Calendar
класс, такой как следующий
public static void addDays(Date d, int days)
{
d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}
Это получает значение метки времени даты (миллисекунды с начала эпохи) и добавляет правильное количество миллисекунд. Вы можете передать отрицательное целое число для параметра дней, чтобы сделать вычитание. Это было бы проще, чем "правильное" календарное решение:
public static void addDays(Date d, int days)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DATE, days);
d.setTime( c.getTime().getTime() );
}
Обратите внимание, что оба эти решения меняют Date
Объект передается в качестве параметра, а не возвращает совершенно новый Date
, Любая функция может быть легко изменена, чтобы сделать это другим способом при желании.
Ответ Ансона подойдет для простого случая, но если вы собираетесь делать более сложные вычисления даты, я бы порекомендовал проверить Joda Time. Это сделает вашу жизнь намного проще.
К вашему сведению в Joda Time вы могли бы сделать
DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);
ТЛ; др
LocalDate.now().minusDays( 10 )
Лучше указать часовой пояс.
LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )
подробности
Старые классы даты и времени, связанные с ранними версиями Java, такие как java.util.Date
/ .Calendar
, оказались хлопотными, запутанными и ошибочными. Избежать их.
java.time
Java 8 и более поздние версии вытесняют эти старые классы новой платформой java.time. Смотрите учебник. Определено JSR 310, вдохновлено Joda-Time и расширено проектом ThreeTen-Extra. Проект ThreeTen-Backport переносит классы на Java 6 и 7; проект ThreeTenABP для Android.
Вопрос неопределенный, неясно, запрашивает ли он только дату или дату-время.
LocalDate
Только для даты, без времени суток, используйте LocalDate
учебный класс. Обратите внимание, что часовой пояс имеет решающее значение при определении даты, такой как "сегодня".
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );
ZonedDateTime
Если вы имели в виду дату и время, используйте Instant
класс, чтобы получить момент на временной шкале в UTC. Оттуда установите часовой пояс, чтобы получить ZonedDateTime
объект.
Instant now = Instant.now(); // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
Где взять классы java.time?
- Java SE 8, Java SE 9, Java SE 10 и более поздние версии
- Встроенный.
- Часть стандартного Java API со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
int x = -1;
Calendar cal = ...;
cal.add(Calendar.DATE, x);
редактировать: парсеру, похоже, не нравится ссылка на Javadoc, так что здесь она в текстовом виде:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html, int)
Вместо того, чтобы писать свой собственный addDays
как предположил Эли, я бы предпочел использовать DateUtils
от Apache. Это удобно, особенно когда вам нужно использовать его в нескольких местах в вашем проекте.
API говорит:
addDays(Date date, int amount)
Добавляет количество дней к дате, возвращая новый объект.
Обратите внимание, что он возвращает новый Date
объект и не вносит изменений в саму предыдущую.
Я столкнулся с той же проблемой, когда мне нужно было вернуться на 1 день (должен иметь возможность откатиться на один, даже если предыдущий день приходится на предыдущий год или месяцы).
Я сделал следующее, в основном вычтя по 24 часа в течение 1 дня.someDateInGregorianCalendar.add(Calendar.HOUR, -24);
В качестве альтернативы я мог бы также сделать
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, 2021);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);
System.out.println("Original: " + cal.getTime());
cal.add(Calendar.DATE, -1);
System.out.println("After adding DATE: " + cal.getTime());
ВЫХОД:
Original: Fri Jan 01 15:08:33 CET 2021
After adding DATE: Thu Dec 31 15:08:33 CET 2020
Я считаю, что чистый и приятный способ выполнить вычитание или сложение любой единицы времени (месяцы, дни, часы, минуты, секунды, ...) может быть достигнут с использованием класса java.time.Instant.
Пример вычитания 5 дней из текущего времени и получения результата как Дата:
new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());
Другой пример вычитания 1 часа и прибавления 15 минут:
Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));
Если вам нужна более высокая точность, Instance измеряет до наносекунд. Способы манипулирования наносекундной частью:
minusNano()
plusNano()
getNano()
Также имейте в виду, что Date не так точен, как Instant.
Это может быть легко сделано следующим
Calendar calendar = Calendar.getInstance();
// from current time
long curTimeInMills = new Date().getTime();
long timeInMills = curTimeInMills - 5 * (24*60*60*1000); // `enter code here`subtract like 5 days
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
// from specific time like (08 05 2015)
calendar.set(Calendar.DAY_OF_MONTH, 8);
calendar.set(Calendar.MONTH, (5-1));
calendar.set(Calendar.YEAR, 2015);
timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
Кто-то рекомендовал Joda Time так - я использую этот класс CalendarDate http://calendardate.sourceforge.net/
Это несколько конкурирующий проект с Joda Time, но гораздо более базовый только в 2 классах. Это очень удобно и отлично работает для того, что мне нужно, так как я не хотел использовать пакет больше, чем мой проект. В отличие от аналогов Java, его наименьшая единица - это день, поэтому это действительно дата (без указания миллисекунд или чего-то в этом роде). После того как вы создали дату, все, что вы делаете для вычитания, это что-то вроде myDay.addDays(-5), чтобы вернуться на 5 дней назад. Вы можете использовать его, чтобы найти день недели и тому подобное. Другой пример:
CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);
А также:
//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
dayLabel = cdf.format(currDay);
if (currDay.equals(today))
dayLabel = "Today";//print "Today" instead of the weekday name
System.out.println(dayLabel);
currDay = currDay.addDays(1);//go to next day
}
Второе решение Эли Кортрайт неверно, оно должно быть:
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());