Ответ 1
Для добавления это действительно не имеет значения, но это
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.DAY_OF_YEAR));
печатает
28
363
Я хочу увеличить определенную дату на 1 день. Я создаю объект Calendar, например:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2012);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);
Затем, чтобы увеличить его на 1 день, я могу сделать 2 вещи:
cal.add(Calendar.DAY_OF_MONTH, 1);
ИЛИ
cal.add(Calendar.DAY_OF_YEAR, 1);
Существуют и другие константы "Дня", но я получаю тот же результат, используя вышеприведенные 2 метода увеличения дня на 1. В каком случае я получу разные результаты для двух?
Для добавления это действительно не имеет значения, но это
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.DAY_OF_YEAR));
печатает
28
363
Calendar.add
Добавляет или вычитает указанное количество времени в данное поле календаря на основе правил календаря.
Здесь у вас есть список полей календаря, которые вы можете добавить или вычесть:
MILLISECOND
- это количество миллисекунд от 0 до 999
SECOND
- количество секунд от 0 до 59
MINUTE
- количество минут от 0 до 59
HOUR
- это количество часов от 0 до 11
HOUR_OF_DAY
- количество часов от 0 до 23
DAY_OF_WEEK
- день относительно недели между 1 и 7
DAY_OF_MONTH
- день по отношению к месяцу между 1 и 31
DAY_OF_YEAR
- день относительно года между 1 и 365
WEEK_OF_MONTH
- неделя по отношению к месяцу, начиная с 1
WEEK_OF_YEAR
- неделя по отношению к году, начиная с 1
MONTH
- это месяц относительно года между 0 и 11
YEAR
- количество лет, начиная с 1
Часы, дни и недели имеют несколько полей, но не имеет значения, какое из них вы выберете 1. Например, использование -8 для DAY_OF_WEEK
будет работать.
calendar.add(Calendar.DAY_OF_MONTH, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_WEEK, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_YEAR, -2); // subtract 2 days
calendar.add(Calendar.YEAR, -2); // subtract 2 years
1Не имеет значения только использование Calendar.add
, с другими операциями результаты могут отличаться.
Используйте Calendar.DATE
для своих целей. В вашем случае эти три константы являются синонимами.
Это не имеет никакого значения, когда вы вызываете add. Однако получатели возвращают разные результаты: D
фрагмент кода из GregorianCalendar#add
case DAY_OF_MONTH: // synonym of DATE
case DAY_OF_YEAR:
case DAY_OF_WEEK:
break;
DAY_OF_YEAR
Номер поля для получения и установки, указывающий номер дня в текущем году
DAY_OF_MONTH
Номер поля для получения и установки, указывающий день месяца. Это синоним DATE
Вы увидите разницу, если день больше 31.
Вы по существу увеличиваете дату на один, в обоих случаях. Таким образом, нет разницы в обоих подходах.
Но придерживаться одного метода будет обеспечивать согласованность в вашей кодовой базе, сопровождающие будут чувствовать себя как дома, и, вероятно, среда выполнения оптимизирует вызов метода, компилируя его.
На самом деле, может быть и будет разница в зависимости от того, какой тип поля вы выберете:
* http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html
Модель использования.
Чтобы мотивировать поведение add() и roll(), рассмотрим компонент пользовательского интерфейса с кнопками увеличения и уменьшения для месяц, день и год и базовый GregorianCalendar. Если интерфейс читается 31 января 1999 года, а пользователь нажимает месяц кнопку увеличения, что он должен читать? Если основной реализация использует set(), это может быть прочитано 3 марта 1999 года. Лучше результатом будет 28 февраля 1999 года. Кроме того, если пользователь нажимает кнопку приращения месяца, она должна быть прочитана 31 марта 1999 г., а не 28 марта 1999 года. Сохраняя исходную дату и используя либо add(), либо roll(), в зависимости от того, должны ли быть затронуты большие поля, пользовательский интерфейс может вести себя так, как будет ожидать большинство пользователей.
LocalDate.of( 2012 , Month.JANUARY , 31 )
.plusDays( 1 )
2012-02-01
…или же…
LocalDate.of( 2012 , 1 , 31 ) // Sane numbering: 1-12 for January-December, and '2012' means year 2012.
.plusDays( 1 )
2012-02-01
Класс Calendar
сбивает с толку, неуклюж, и плохо разработан. Среди многих проблем - методы передачи флага. К счастью, теперь вы можете забыть все об этом классе.
Классы java.time, встроенные в Java 8 и более поздние версии, теперь вытесняют устаревшие классы даты и времени.
LocalDate
Класс LocalDate
представляет значение только для даты без времени суток и без часового пояса.
Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция - новый день, а в Монреале-Квебеке все еще "вчера".
Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент, поэтому ваши результаты могут отличаться. Лучше явно указать желаемый/ожидаемый часовой пояс в качестве аргумента.
Укажите правильное имя часового пояса в формате continent/region
, например, America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 3-4-буквенное сокращение, такое как EST
или IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
Если вы хотите использовать текущий часовой пояс по умолчанию для JVM, попросите его и передайте в качестве аргумента. Если опущено, текущее значение по умолчанию для JVM применяется неявно. Лучше быть явным, поскольку значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVMs current default time zone.
Или укажите дату. Вы можете установить месяц по номеру, с нормальным номером 1-12 для января-декабря.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Или, лучше, использовать предварительно определенные объекты перечисления Month
, по одному на каждый месяц года. Совет: используйте эти объекты Month
всей вашей кодовой базе, а не просто целое число, чтобы сделать ваш код более самодокументированным, обеспечить допустимые значения и обеспечить безопасность типов.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Имея LocalDate
в руках, вы можете LocalDate
его части.
Чтобы получить день месяца, то есть "дату", например 23
от 23 января 2018 года:
int dayOfMonth = ld.getDayOfMonth() ; // 1-31, depending on length of month.
Чтобы получить n-й день в году, 1-365 или високосный год, 1-366:
int dayOfYear = ld.getDayOfYear() ;
Добавление или вычитание дней довольно просто и интуитивно понятно в java.time. Удобные методы и объекты промежутка времени делают код намного более понятным.
LocalDate dayLater = ld.plusDays( 1 ) ;
Итак, завтрашний день будет:
LocalDate tomorrow = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ).plusDays( 1 ) ;
В качестве альтернативы вы можете представить промежуток времени, не привязанный к временной шкале. Для лет-месяцев-дней используйте Period
. Для часов-минут-секунд используйте Duration
.
Period p = Period.ofDays( 1 ) ;
LocalDate dayLater = ld.plus( p ) ;
Обратите внимание, что java.time использует разумную нумерацию, в отличие от устаревших классов. Число 2018
- это год 2018. Месяцы с 1 по 12 для января-декабря. Дни недели с понедельника по воскресенье пронумерованы 1-7 в соответствии со стандартом ISO 8601.
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытеснять неприятные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, и SimpleDateFormat
.
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск для многих примеров и объяснений. Спецификация JSR 310.
Где взять классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и другие.
В дополнение к дате не имеет значения, используете ли вы DAY_OF_MONTH или DAY_OF_YEAR. Однако это имеет смысл, когда вы получаете call getter и передаете один из них.
Использовать DATE или DAY_OF_MONTH оба одинаковы
Вот разница:
DATE or DAY_OF_MONTH : Get and Set indicating the day of the month
DAY_OF_WEEK : get and set indicating the week number within the current month
DAY_OF_YEAR : get and set indicating the day number within the current ye
Источник: https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html