Nano Hash - криптовалюты, майнинг, программирование

Calender.set() не работает должным образом

Я хочу получить дату окончания последнего месяца, я получаю текущий месяц, возвращаю его на единицу и устанавливаю значение этого месяца. Но Calender.set(Calender.Month, lastMonth) не работает только для определенной даты.

public static String getLastMonthEndDate(Date nowDate, String dateFormat) 
{
    final String METHOD_NAME = "getLastMonthEndDate" ;


    SimpleDateFormat formatedDate = new SimpleDateFormat(dateFormat);


    Calendar calendar = new GregorianCalendar(2014, Calendar.OCTOBER, 31); // Hard coded as 2014, oct 31st for the sake of example.
    //calendar.setTime(nowDate);
    System.out.println(calendar.getTime());
    if(calendar.get(Calendar.MONTH) == Calendar.JANUARY)
    {
        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1);
    }

    //System.out.println("calendar.get(Calendar.MONTH) -1 : " + (calendar.get(Calendar.MONTH) -1));
    int lastMonth = (calendar.get(Calendar.MONTH) -1);
    System.out.println("Last month : "+lastMonth);
    calendar.set(Calendar.MONTH, lastMonth);
    //System.out.println(calendar.getTime());
    //System.out.println("(calendar.get(Calendar.MONTH) : " + calendar.get(Calendar.MONTH));
    System.out.println("calendar.getActualMaximum(Calendar.DAY_OF_MONTH) : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

    calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
    System.out.println("calendar.getTime() : " + calendar.getTime());

    return formatedDate.format(calendar.getTime());
}



public static void main(String[] args)
{

     Date dCurrentDate = getCurrentDate();
     String strLastMonthEndDateInYYYY = getLastMonthEndDate(dCurrentDate, "MM/dd/yyyy");
     System.out.println("strLastMonthEndDateInYYYY : "+strLastMonthEndDateInYYYY);

}

Ниже приведен результат, который я получил

output : 


Fri Oct 31 00:00:00 IST 2014

Last month : 8

calendar.getActualMaximum(Calendar.DAY_OF_MONTH) : 31

calendar.getTime() : Wed Oct 01 00:00:00 IST 2014

strLastMonthEndDateInYYYY : 10/01/2014

Я не знаю, где ошибка. Пожалуйста помоги.


  • Возможно, вам нужно посмотреть это 04.11.2014
  • @hagubear Не имеет никакого значения, поскольку Calendar.OCTOBER — это не что иное, как 9. Поскольку 0 представляет январь. 04.11.2014
  • Почему бы вам просто не использовать Calendar.add(Calendar.Month, -1) для вычитания месяца? Тогда вам не нужно делать арифметику года для себя. 04.11.2014
  • Вы не должны использовать set(), но add() с -1 для месяца. Иначе дни будут портить вам настроение ;) 04.11.2014

Ответы:


1

Это не работает, потому что вы устанавливаете дату «31.09.2014» после ваших операций с календарем, а в сентябре 2014 года нет 31-го дня. По умолчанию java Calendar снисходительный, и будет интерпретировать эту дату как "01.10.2014" (1 октября 2014 г.).

Вот соответствующая часть Javadoc:

Когда календарь находится в мягком режиме, он принимает более широкий диапазон значений полей календаря, чем выдает. Когда Calendar повторно вычисляет значения полей календаря для возврата с помощью get(), все поля календаря нормализуются. Например, мягкий GregorianCalendar интерпретирует MONTH == JANUARY, DAY_OF_MONTH == 32 как 1 февраля.

И вот закомментированная версия соответствующих частей вашего кода, чтобы объяснить, что происходит:

Calendar calendar = new GregorianCalendar(2014, Calendar.OCTOBER, 31); // 10/31/2014
// [...]
int lastMonth = (calendar.get(Calendar.MONTH) -1); // lastMonth will be Calendar.SEPTEMBER
calendar.set(Calendar.MONTH, lastMonth); // internal value of the calendar is now 09/31/2014
// [..]
System.out.println("calendar.getActualMaximum(Calendar.DAY_OF_MONTH) : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // returns 31 because this is a get() method, so 09/31/2014 will be converted to 10/01/2014, and there are 31 days in October (but the internal representation of the calendar will still be 09/31/2014)
// [...]
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // internal representation is still 09/31/2014, so this will not change the value
// [...]
return formatedDate.format(calendar.getTime()); // this is a get() method, so the value will be converted to 10/01/2014

Лучшим решением было бы установить Calendar на первый день месяца и вычесть один день:

Calendar calendar = new GregorianCalendar(2014, 9, 31);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.DAY_OF_MONTH, -1);
System.out.println((new SimpleDateFormat("MM/dd/yyyy")).format(calendar.getTime())); // 09/30/2014
04.11.2014
  • Где я устанавливаю 31 в сентябре 2014? 04.11.2014
  • @codeMan Отредактировал мой ответ, чтобы показать вам, где вы неправильно настраиваете календарь. 04.11.2014
  • да, последняя строка возвращает 31, потому что это октябрь. Если это так, вывод должен был быть 10/31/2014, но почему он 10/01/2014 04.11.2014
  • @codeMan Поскольку lenient влияет только на значения, возвращаемые функциями get(), а не на внутреннее представление календаря, я отредактирую свой пост, чтобы отразить это. 04.11.2014

  • 2

    Ну, причина, по которой я вижу, что вы установили свою дату как:

    Calendar calendar = new GregorianCalendar(2014, 9, 31);
    

    Если вы посмотрите на календарь, в 9-м месяце (сентябрь) всего 30 дней. Таким образом, ваша дата автоматически устанавливается как (2014/10/1) вместо (2014,9,31)

    04.11.2014
  • Нет. Октябрь представлен цифрой 9. Так как январь начинается с 0. 04.11.2014
  • docs.oracle.com/javase/7/ docs/api/java/util/Calendar.html#MONTH говорит, что он прав 04.11.2014

  • 3

    Вы можете использовать Calendar.add(Calendar.Month, -1), чтобы перейти к предыдущему месяцу, и установить максимальный день этого месяца.

    как:

    public static Date getLastMonthLastDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
    
        int max = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, max);
    
        return calendar.getTime();
    }
    

    Подробнее здесь

    04.11.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..