Получите тот же день с этого года - PullRequest
0 голосов
/ 06 февраля 2019

Мне нужно получить тот же день в этом году.

Пример: сейчас 2019 год, а переменная содержит значение 15 июля 2022 года, поэтому мне нужно получить 15 июля 2019 года.Он работает для всех дат, кроме февраля, когда у него есть дополнительный день в году и у него нет этого дня в этом году, например: 29 февраля 2020 года вернет меня на следующий день: 1 марта 2019 года, но мне нужно в этом случаевозвратите предыдущий день: 28 февраля 2019 года. Как я могу настроить свою логику так, чтобы она работала таким образом?

public static java.util.Date getThisDateInThisYear(java.util.Date date) {
    GregorianCalendar gc = new GregorianCalendar();
    gc.setTime(date);
    Date today = new Date();
    GregorianCalendar gcToday = new GregorianCalendar();
    gcToday.setTime(today);
    gc.set(GregorianCalendar.YEAR, gcToday.get(GregorianCalendar.YEAR));
    return gc.getTime();
  }

Ответы [ 4 ]

0 голосов
/ 07 февраля 2019

Я не вижу проблем с java.util.Calendar.В JDK 1.8 этот класс Java получил серьезные переделки.Итак, следующий пример кода работает нормально:

    SimpleDateFormat sf = new SimpleDateFormat("dd MMM yyyy");
    Date date=sf.parse("29 Feb 2020");
    System.out.println("date="+date);

    Calendar calendar=Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.YEAR, -1);
    System.out.println("date="+calendar.getTime());

    calendar.add(Calendar.YEAR, 1);
    System.out.println("date="+calendar.getTime());

Он дает тот же результат, который хочет получить Бэзил Бурк:

date=Sat Feb 29 00:00:00 CET 2020
date=Thu Feb 28 00:00:00 CET 2019
date=Fri Feb 28 00:00:00 CET 2020

В основном класс Java теперь использует ту же ZoneInfo и т. Д..классы, как и новые классы.

0 голосов
/ 06 февраля 2019

Также вы можете проверить, является ли год високосным, исходя из того, что вы можете вычесть дату

public static boolean isLeapYear(int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}
0 голосов
/ 06 февраля 2019

tl; dr

Используйте современные java.time классы.Никогда не используйте Date / Calendar.

29 февраля 2020 г. вернет меня на следующий день: 1 марта 2019 г.

LocalDate                           // Represent a date-only value, without time-of-day and without time zone.
.of( 2020 , Month.FEBRUARY , 29 )   // Specify a date. Here, Leap Day of 2020. Returns a `LocalDate` object.
.minusYears( 1 )                    // Intelligently move backwards in time one year. Returns another `LocalDate` object, per immutable objects pattern.
.toString()                         // Generate text representing the value of this date, in standard ISO 8601 format of YYYY-MM-DD.

Когда запустится на IdeOne.com :

2019-02-28

Избегайте устаревших классов даты и времени

Вы используете ужасные классы даты и времени, которые теперь унаследованы, полностью вытесненные java.time классы.

LocalDate

Класс LocalDate представляет значение только для даты без времени суток и без часовой пояс или смещение от UTC .

Часовой пояс имеет решающее значение при определении даты.В любой момент времени дата меняется по всему земному шару в зависимости от зоны.Например, через несколько минут после полуночи в Париж Франция - это новый день, в то время как "вчера" в Монреаль Квебек .

Если часовой пояс не указан,JVM неявно применяет свой текущий часовой пояс по умолчанию.Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться.Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента.

Укажите собственное имя часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca,или Pacific/Auckland.Никогда не используйте 2-4 буквенные сокращения, такие как EST или IST, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента.Если опущен, код становится неоднозначным для чтения, поскольку мы точно не знаем, намеревались ли вы использовать значение по умолчанию или если вы, как и многие другие программисты, не знали о проблеме.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Или укажитесвидание.Вы можете установить месяц по номеру, с нормальным номером 1-12 для января-декабря.

LocalDate ld = LocalDate.of( 2020 , 2 , 29 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Или, лучше, использовать предварительно определенные объекты перечисления Month, по одному на каждый месяц года.Совет: используйте эти Month объекты по всей вашей кодовой базе, а не просто целое число, чтобы сделать ваш код более самодокументируемым, обеспечить допустимые значения и обеспечить type-safety .То же самое для Year & YearMonth.

LocalDate ld = LocalDate.of( 2020 , Month.FEBRUARY , 29 ) ;

Математика даты и времени

Математика даты и времени может быть выполнена внесколько способов с * java.time.Один из способов - позвонить по номеру plus или minus и передать Period или Duration.Другим способом является вызов вспомогательных методов, таких как plusYears или minusYears.

Класс LocalDate, кажется, дает именно то поведение, которое вы хотите с помощью этих методов.

Для ясности:

  • 2020 - високосный год.Таким образом, 2020-02-29 является действительной датой.
  • 2018, 2019 и 2021 - нет.29-е число не действительная дата в эти годы.

См. Примеры ниже запустить в прямом эфире на IdeOne.com .

Свисокосный год

Давайте начнем с високосного дня, 29-го числа, затем добавим год и вычтем год.Мы ожидаем увидеть 28-е место в обоих случаях.

LocalDate leapDay2020 = LocalDate.of( 2020 , Month.FEBRUARY , 29 );
LocalDate yearBeforeLeap = leapDay2020.minusYears( 1 );
LocalDate yearAfterLeap = leapDay2020.plusYears( 1 );

System.out.println( "leapDay2020.toString(): " + leapDay2020 );
System.out.println( "yearBeforeLeap.toString(): " + yearBeforeLeap );
System.out.println( "yearAfterLeap.toString(): " + yearAfterLeap );

Действительно, это то, что мы получаем.

leapDay2020.toString (): 2020-02-29

yearBeforeLeap.toString (): 2019-02-28

yearAfterLeap.toString (): 2021-02-28

Из неисключительного года

Теперь давайтеначните не в високосный год 28 февраля, затем добавьте и вычтите год.Мы ожидаем увидеть 28-е место во всех трех.29-й в високосном году 2020 игнорируется.

LocalDate nonLeap2019 = LocalDate.of( 2019 , Month.FEBRUARY , 28 );
LocalDate yearBeforeNonLeapIntoNonLeap = nonLeap2019.minusYears( 1 );
LocalDate yearBeforeNonLeapIntoLeap = nonLeap2019.plusYears( 1 );

System.out.println( "nonLeap2019.toString(): " + nonLeap2019 );
System.out.println( "yearBeforeNonLeapIntoNonLeap.toString(): " + yearBeforeNonLeapIntoNonLeap );
System.out.println( "yearBeforeNonLeapIntoLeap.toString(): " + yearBeforeNonLeapIntoLeap );

nonLeap2019.toString (): 2019-02-28

yearBeforeNonLeapIntoNonLeap.toString (): 2018-02-28

yearBeforeNonLeapIntoLeap.toString (): 2020-02-28


О java.time

* java.time Framework встроен в Java 8 и более поздние версии.Эти классы вытесняют старые классные устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

йe Проект 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 SE 11 и более поздние версии - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большинство функций java.time перенесено в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии пакетов Android для реализации java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

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

0 голосов
/ 06 февраля 2019

сначала вычислите разницу лет и добавьте результат к дате

public Date getThisDateInThisYear(Date date) {
   Calendar c = Calendar.getInstance();
   int thisYear = c.get(Calendar.YEAR)
   c.setTime(date);

   int diff = thisYear  - c.get(Calendar.YEAR);
   c.add(Calendar.YEAR, diff);

   return c.getTime();

}

Я тестировал с 2016-02-29 и 2020-02-29, и оба возвращаем 2019-02-28.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...