Самый простой способ добавить месяц к типу 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

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval, YearWeek, YearQuarter и многое другое.

Другие вопросы по тегам