Добавить 1 неделю к дате, какой путь предпочтительнее? - PullRequest
25 голосов
/ 21 июля 2010

Я проверяю некоторый код на работе и натолкнулся на несоответствие в том, как код обрабатывает добавление 1 недели к текущему времени, и мне было интересно, есть ли какая-либо причина, по которой один из них действительно предпочтительнее другого:

Первый - это служебный метод:

public static Date addDaysToDate(final Date date, int noOfDays) {
    Date newDate = new Date(date.getTime());

    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(newDate);
    calendar.add(Calendar.DATE, noOfDays);
    newDate.setTime(calendar.getTime().getTime());

    return newDate;
}

А второй - простая арифметика в миллисекундах:

long theFuture = System.currentTimeMillis() + (86400 * 7 * 1000);
Date nextWeek = new Date(theFuture);

Второй метод, очевидно, использует «магические числа» для определения недели, но этоможно перевести в константу MILLISECONDS_IN_ONE_WEEK = 86400 * 7 * 1000 Итак, есть ли другие причины, по которым один из этих методов предпочтительнее другого?

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

Ответы [ 10 ]

22 голосов
/ 21 июля 2010

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

3 голосов
/ 15 августа 2016

Ниже можно сделать в Java 8, Java 8 пород !!

public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("Current date: " + today);

        //add 1 week to the current date
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        System.out.println("Next week: " + nextWeek);
    }
3 голосов
/ 21 июля 2010

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

private static long ONE_YEAR_AS_MILLISECONDS = 365*24*60*60*1000;

Это выглядит достаточно невинно, но на самом деле не даст ожидаемого результата, поскольку при умножении используются целые числа, которые при умножении на другие целые числа вызывают числовое переполнение и дают неожиданный результат. Это связано с тем, что максимальное значение int в Java составляет 2 147 483 647, а в год - 31 536 000 000 мс. На моей машине приведенный выше код выдает 1,471,228,928, что явно не правильно.

Вместо этого вам нужно сделать следующее:

private static long ONE_YEAR_AS_MILLISECONDS = 365L*24L*60L*60L*1000L;
1 голос
/ 21 июля 2010

Прежде всего, я бы сказал, что вы замените его на JodaTime.http://joda -time.sourceforge.net / Это очень хорошая библиотека времени.Вы захотите взглянуть на эту страницу, чтобы увидеть, как легко добавить дни или недели к определенному моменту времени: http://joda -time.sourceforge.net / key_period.html МожетЭто мобильное устройство с несовместимой JVM.Облом.

Ваш первый пример легче читается и будет проще в использовании вашим разработчикам.Он также использует классы Calendar, которые являются общепринятым способом манипулирования датами в Java.Что делает его лучше, так это то, что у него есть четкое имя метода, которое устанавливает ожидание того, что он делает.

Так что если вы реорганизуете свою систему, чтобы последовательно использовать com.DaveJ.util.date.DateUtils.addDaysToDate (final Datedate, int noOfDays) вы можете делать все, что захотите, внутри этого метода, будь то Calendar, Millis или Joda, и быть последовательными в своем приложении.Не забудьте написать для него несколько юнит-тестов!

0 голосов
/ 15 августа 2016

Значение только для даты см. Ответ от javaHelper .Класс LocalDate специально не имеет времени суток и часового пояса.

ZonedDateTime

Для значения даты-времени используйте ZonedDateTime для представления даты и времени суток вместе с часовым поясом для учета таких аномалий, как летнее время (DST).

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime weekLater = now.plusWeeks( 1 );

Или добавьте произвольное числодней.

ZonedDateTime later = now.plusDays( someNumberOfDays );

О java.time

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

Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на java.time.

Подробнее см. Oracle Tutorial .И поищите в Stack Overflow множество примеров и объяснений.

Большая часть функциональности java.time перенесена в Java 6 & 7 в ThreeTen-Backport и дополнительно адаптирована для Android in ThreeTenABP .

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

0 голосов
/ 21 июля 2010

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

Вы должны удалить зависимость от GregorianCalendar и создать ее, используя Calendar.getInstance().

0 голосов
/ 21 июля 2010

Эти два метода могут давать разные результаты, если речь идет о переходе на летнее время.Представьте, что текущее время - 23:50, а в 02:00 часы переходят на 03:00.Когда вы просто добавляете 7 дней в миллисекундах, время будет 00:50 на следующий день.Если добавить 7 дней, итоговое время все равно будет 23: 50.

Чтобы завершить путаницу, вы также можете попробовать add(Calendar.WEEK_OF_YEAR, 1), хотя и не знаете, как это будет отличаться.

0 голосов
/ 21 июля 2010

Это зависит! Из-за високосных секунд, летнего времени и других странностей календаря они не всегда эквивалентны.

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

Для научных нужд часто приходится использовать монотонные часы (здесь вторые).

0 голосов
/ 21 июля 2010

Первый будет медленнее, поэтому, если производительность является проблемой, второй лучше.

0 голосов
/ 21 июля 2010

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

...