Добавьте 1 неделю к дате, какой путь является предпочтительным?
Я просматриваю код на работе и сталкиваюсь с несогласованностью в том, как код обрабатывает добавление 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
Так, кроме этого, есть ли причины, по которым один из этих методов должен быть предпочтительнее другого?
В основном я хочу изменить код, чтобы он был согласованным во всем, но я не совсем уверен, какой из них удалить. Поэтому любые аргументы так или иначе будут полезны.
Ответы
Ответ 1
Оба метода будут вести себя по-разному на границах с дневным сбережением. Первый метод будет продолжать возвращаться в то же время дня, независимо от состояния летнего времени. Второй метод будет возвращать время, которое изменяется в течение часа в каждом направлении, когда начинается и останавливается летнее время.
Ответ 2
Будьте очень осторожны с использованием метода, который поймал меня на днях. Рассмотрим
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;
Ответ 3
Ниже можно сделать в 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);
}
Ответ 4
Прежде всего, я бы сказал, что вы замените его на JodaTime. http://joda-time.sourceforge.net/ Это очень хорошая библиотека времени. Вы захотите просмотреть эту страницу, чтобы увидеть, как легко добавлять дни или недели к определенному моменту времени: http://joda-time.sourceforge.net/key_period.html Невозможно это сделать, мобильное устройство с несовместимой JVM. Облом.
Ваш первый пример легче читать и будет проще использовать ваши разработчики. Он также использует классы Calendar, которые являются общепринятым способом манипулирования датами в Java. Что делает его лучше, так это то, что у него есть ясное имя метода, которое задает ожидания для того, что он делает.
Итак, если вы реорганизуете свою систему, чтобы последовательно использовать com.DaveJ.util.date.DateUtils.addDaysToDate(окончательная дата date, int noOfDays), вы можете делать все, что захотите внутри этого метода, будь то календарь или миллис или Джода, и быть последовательным в вашей заявке. Не забудьте написать для него некоторые модульные тесты!
Ответ 5
Чем более общим, тем более полезным оно будет.
Если вы всегда добавляете неделю, я бы выбрал второй метод. Если у вас есть разные добавления, я бы выбрал первый, возможно, заменив дни в секундах или даже миллисах, если это необходимо.
Ответ 6
Первый будет медленнее, поэтому, если производительность является проблемой, вторая лучше.
Ответ 7
Это зависит! Из-за секунд прыжка, DST и других календарных странностей эти два не всегда эквивалентны.
Для бизнеса и повседневного использования всегда используйте первый метод, а производительность - неплохая. Он будет обрабатывать эти вещи для вас.
Для научных нужд часто приходится использовать монотонные часы (здесь второй).
Ответ 8
Эти два метода могут давать разные результаты, когда задействовано изменение летнего времени. Представьте себе, что текущее время 23:50, а в 02:00 часы прыгают до 03:00. Когда вы просто добавите 7 дней в миллисекундах, на следующий день будет 00:50. Добавления 7 дней, результирующее время все равно будет 23:50.
Чтобы сделать путаницу законченной, вы также можете попробовать add(Calendar.WEEK_OF_YEAR, 1)
, не знаете, как это будет отличаться.
Ответ 9
Поскольку вы используете его на мобильном устройстве, предпочтительным является первый метод. Причина в том, что ваш код должен быть независимым от конкретного календаря, летнего времени и других проблем, таких как переполнение секунд (прыжок секунд).
Вам нужно удалить зависимость от GregorianCalendar
и создать ее с помощью Calendar.getInstance()
.
Ответ 10
Для значения только для даты см. Ответ 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. И поиск Qaru для многих примеров и объяснений.
Большая часть функциональных возможностей java.time обратно переносится на Java 6 и 7 в ThreeTen-Backport и далее адаптируется к Android в ThreeTenABP.
Проект ThreeTen-Extra расширяет java.time с помощью дополнительных классов. Этот проект является доказательством возможных будущих дополнений к java.time.