Apache DateUtils усекать день месяца

Я хотел бы создать класс DateHelper и для этого я использую DateUtils из Apache Commons Lang 2.6. У меня проблемы с пониманием результата, возвращаемого при извлечении поля из даты. Вот мой тестовый класс, который извлекает день месяца после усечения даты:

    public class DateTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
//      Date date = createDate(2000, 1, 2, 3, 4, 5, 6);

        Calendar calendar = createEmptyUTCCalendar();
        calendar.set(Calendar.YEAR, 2000);
        calendar.set(Calendar.MONTH, 0); // january
        calendar.set(Calendar.DAY_OF_MONTH, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 3);
        calendar.set(Calendar.MINUTE, 4);
        calendar.set(Calendar.SECOND, 5);
        calendar.set(Calendar.MILLISECOND, 6);

        Date date = calendar.getTime();
    System.out.println("Input date\n" + date);

    // Truncate from day of month.
    Date dateTruncate = getDatePart(date);
    System.out.println("Truncate the date\n" + dateTruncate);

    System.out.println("\n*** Extract day of month ***");
    // Extract the field day of month from the truncated date.
    int fieldDayOfMonth = getField(dateTruncate, Calendar.DAY_OF_MONTH);
    System.out.println("Expected result is 2\nActual result is " + fieldDayOfMonth);

        assert fieldDayOfMonth == 2;
    }

     public static int getField(Date date, int calendarField) {
        Calendar calendar = createEmptyUTCCalendar();
        calendar.setTime(date);
        int value = calendar.get(calendarField);
        if (calendarField == Calendar.MONTH) {
            value++;
        }
        return value;
    }

    public static Date getDatePart(Date date) {
        return DateUtils.truncate(date, Calendar.DAY_OF_MONTH);
    }

    private static Calendar createEmptyUTCCalendar() {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
        return calendar;
    }
}

Я ожидаю, что результатом извлечения поля Calendar.DAY_OF_MONTH будет 2, но я получил 1.

Input date
Sun Jan 02 04:04:05 CET 2000
Truncate the date
Sun Jan 02 00:00:00 CET 2000

*** Extract day of month ***
Expected result is 2
Actual result is 1

2 ответа

ТЛ; др

LocalDate.of( 2000 , Month.JANUARY , 2 )
         .getDayOfMonth() 

2

java.time

Вы можете просто использовать Java сейчас, нет необходимости в Apache DateUtils. И усечение - неправильный способ думать об этом; просто допросить за день месяц собственности.

Укажите свою дату, используя LocalDate учебный класс. Обратите внимание на то, что java.time использует нумерацию разумных месяцев, 1-12 для января по декабрь

LocalDate ld = LocalDate.of( 2000 , 1 , 2 ) ;  // January 2, 2000.

Или используйте Month ENUM.

LocalDate ld = LocalDate.of( 2000 , Month.JANUARY , 2 ) ;  // January 2, 2000.

2000-01-02

Допросить за день месяца. Ты можешь позвонить getDayOfMonth на LocalDate, OffsetDateTime, а также ZonedDateTime,

int dayOfMonth = ld.getDayOfMonth​() ;

2

При получении Calendar объект, это, вероятно, GregorianCalendar, Если это так, вы можете легко преобразовать в классы java.time.

if( myCalendar instanceOf GregorianCalendar ) {
    GregorianCalendar gc = ( GregorianCalendar ) myCalendar ;  // Cast.
    ZonedDateTime zdt = gc.toZonedDateTime() ;  // Convert from legacy class to modern class.
    int dayOfMonth = zdt.getDayOfMonth​() ;
} 

О 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 и многое другое.

Кажется, дело в часовых поясах. Ваш календарь на UTC и ваша дата в вашей локальной зоне, если вы избегаете линии:

calendar.setTimeZone(TimeZone.getTimeZone("UTC"));

вещь должна работать.

Когда вы передаете календарь в Date, объект date получает часовой пояс CET по умолчанию в вашем случае. Затем вы усекаете и снова переходите к календарю UTC, и из-за разницы между CET и UTC ваш день является предыдущим.

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