Самый простой способ добавить месяц к типу Java DATE без использования календаря или Joda?
Я работаю в интегрированной среде (IBM Process Server) и не могу ничего импортировать, могу использовать только стандартные функции Java.
Как я могу добавить x количество месяцев к определенной дате?
4 ответа
Учитывая, что у вас есть Дата, импортированная по умолчанию, вы можете добавить количество месяцев к объекту даты следующим образом:
public void addMonths(Date date, int numMonths){
date.setMonth((date.getMonth() - 1 + numMonths) % 12 + 1);
}
НОТА
Вы можете использовать внешние классы из Java SE, используя их полное имя пакета. т.е. даже если вы не можете добавить import java.util.Calendar;
к вам .java
файл, вы все еще можете создать объект календаря, выполнив java.util.Calendar cal = java.util.Calendar.getInstance();
Если вы хотите реализовать без календаря, используйте предложение @ewok при работе с устаревшим методом, используйте следующий код:
SimpleDateFormat dt1 = new SimpleDateFormat("yyyy-MM-dd"); //Date format
SimpleDateFormat dt = new SimpleDateFormat("MM");
Date date = dt1.parse("2013-12-31");
int dm=0;
int m = Integer.parseInt(dt.format(date));
switch(m){
case 2:
m = 27;
break;
case 4:
case 6:
case 9:
case 11:
m = 29;
break;
default:
m = 30;
break;
}// Closing switch block
long month = Math.round(1000*60*60*24.25*m);
long oneMonthTime = date.getTime()+month;
System.out.println(dt1.format(oneMonthTime));
Этот код не для високосного года. Я знаю, что это не идеальный, но все еще работающий код.
Ответ @ewok не всегда работает после окончания года, только с numMonths
установите значения ниже или равные месяцам до следующего января:
SSCCE:
public static void main(String[] args) {
for(int i=0;i<10; i++) {
Date date = new Date();
Date updated = (Date)date.clone();
addMonths(updated, i);
System.out.println(" original: " + date+ " adding " +i+ " months: " + updated);
}
}
public static void addMonths(Date date, int numMonths){
date.setMonth((date.getMonth() - 1 + numMonths) % 12 + 1);
}
Выход:
original: Sat Aug 24 14:02:17 CEST 2013 adding 0 months: Sat Aug 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 1 months: Tue Sep 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 2 months: Thu Oct 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 3 months: Sun Nov 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 4 months: Tue Dec 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 5 months: Fri Jan 24 14:02:17 CET 2014
original: Sat Aug 24 14:02:17 CEST 2013 adding 6 months: Sun Feb 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 7 months: Sun Mar 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 8 months: Wed Apr 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 9 months: Fri May 24 14:02:17 CEST 2013
Обратите внимание, что февраль, март и т. Д. Вернулись в 2013 году! Код ошибочен из-за странной арифметики... setMonth обрабатывает значения> 12 тоже...
Исправлено (хотя все еще используется устаревший метод...):
date.setMonth((date.getMonth() + numMonths) );
Выход:
original: Sat Aug 24 14:13:09 CEST 2013 adding 0 months: Sat Aug 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 1 months: Tue Sep 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 2 months: Thu Oct 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 3 months: Sun Nov 24 14:13:09 CET 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 4 months: Tue Dec 24 14:13:09 CET 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 5 months: Fri Jan 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 6 months: Mon Feb 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 7 months: Mon Mar 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 8 months: Thu Apr 24 14:13:09 CEST 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 9 months: Sat May 24 14:13:09 CEST 2014
Что нужно учитывать
Последние дни месяцев из документа Java по setMonth():
Устанавливает месяц этой даты в указанное значение. Этот объект Date изменен таким образом, чтобы он представлял точку времени в течение указанного месяца, где год, дата, час, минута и секунда такие же, как и раньше, как интерпретируется в местном часовом поясе. Например, если дата была 31 октября, а месяц установлен на июнь, то новая дата будет рассматриваться, как если бы она была 1 июля, поскольку в июне всего 30 дней.
Тем не менее, устарела - Решение проблемы должным образом заняло бы слишком много времени (в исключительных случаях, високосных днях, високосных секундах и т. Д.), Не говоря уже о полном переосмыслении колеса... Возможно, обрезать календарь до минимума и вставить его в код решит это - но даже это не стоит хлопот...
Определенно следует попробовать второй подход, предложенный @ewok, полностью квалифицированное имя класса.
ТЛ; др
myJavaUtilDate.toInstant() // Convert troublesome legacy `java.util.Date` object to a modern java.time object, `Instant`.
.atZone( ZoneId.of( "Pacific/Auckland" ) ) // Adjust that `Instant` object from UTC to a particular time zone thereby instantiating a `ZonedDateTime` object, to determine dates.
.plus( Period.ofMonths( 6 ) ) // Add six months represented by a `Period` to instantiate another `ZonedDateTime` object.
java.time
Классы java.time встроены в Java 8, Java 9 и более поздние версии. Они вытесняют неприятные старые классы даты и времени, такие как Date
а также Calendar
,
Если вы должны взаимодействовать с существующим Date
объект, преобразовать в java.time. Эквивалент Instant
, Instant
класс представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби). Преобразование с использованием новых методов, добавленных к старым классам.
Instant instant = myJavaUtilDate.toInstant() ;
Instant
это момент в UTC. Добавление шести месяцев требует даты. Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а в Монреале-Квебеке все еще "вчера".
Укажите правильное название часового пояса в формате continent/region
, такие как America/Montreal
, Africa/Casablanca
, или же Pacific/Auckland
, Никогда не используйте 3-4-буквенные псевдозоны, такие как EST
или же IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Настройте свой Instant
в этот часовой пояс, применяя ZoneId
чтобы получить ZonedDateTime
объект.
ZonedDateTime zdt = instant.atZone( z ) ;
Определить шесть месяцев как Period
,
Period p = Period.ofMonths( 6 ) ;
Добавьте это Period
объект для генерации нового ZonedDateTime
объект.
ZonedDateTime later = zdt.plus( p ) ;
Смотрите этот код в прямом эфире на IdeOne.com.
instant.toString (): 2018-01-31T06: 26: 34,580Z
zdt.toString (): 2018-01-31T01: 26: 34.580-05: 00 [Америка / Монреаль]
p.toString (): P6M
later.toString () 2018-07-31T01: 26: 34.580-04: 00 [Америка / Монреаль]
Если вам нужно вернуться к значению в UTC, извлеките Instant
,
Instant instant = later.toInstant() ;
Если вам нужно Date
, перерабатывать. Но старайтесь избегать этого класса, если это возможно.
Date d = Date.from( instant ) ;
Если у вас есть значение только для даты без времени суток, используйте LocalDate
, LocalDate
класс представляет значение только для даты без времени суток и без часового пояса.
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ; // January 23, 2018.
LocalDate later = ld.plusMonths( 6 ) ;
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Где взять классы java.time?
- Java SE 8, Java SE 9 и более поздние
- Встроенный.
- Часть стандартного Java API со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.