Получите количество недель между двумя датами.
Я работаю в проекте и у меня есть два типа в день. Я хочу, чтобы вычислить количество недель между двумя датами. Даты могут быть в разные годы. Есть ли хорошее решение для этого?
Я попытался имплементировать это с Joda-time, который был предложен в других темах..
Я не знаком с этой библиотекой, но я пытался сделать что-то вроде этого:
public static int getNumberOfWeeks(Date f, Date l){
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(f);
c2.setTime(l);
DateTime start = new DateTime(c1.YEAR, c1.MONTH, c1.DAY_OF_MONTH, 0, 0, 0, 0);
DateTime end = new DateTime(c2.YEAR, c2.MONTH, c2.DAY_OF_MONTH, 0, 0, 0, 0);
Interval interval = new Interval(start, end);
Period p = interval.toPeriod();
return p.getWeeks();
}
но это совершенно неправильно... есть предложения ?
12 ответов
Это довольно легко с Джода времени:
DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);
int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();
обновление ответа для учетной записи Java 8
// TechTrip - ASSUMPTION d1 is earlier than d2
// leave that for exercise
public static long getFullWeeks(Calendar d1, Calendar d2){
Instant d1i = Instant.ofEpochMilli(d1.getTimeInMillis());
Instant d2i = Instant.ofEpochMilli(d2.getTimeInMillis());
LocalDateTime startDate = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
LocalDateTime endDate = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());
return ChronoUnit.WEEKS.between(startDate, endDate);
}
используя арифметику даты в java.util.Calendar
:
public static int getWeeksBetween (Date a, Date b) {
if (b.before(a)) {
return -getWeeksBetween(b, a);
}
a = resetTime(a);
b = resetTime(b);
Calendar cal = new GregorianCalendar();
cal.setTime(a);
int weeks = 0;
while (cal.getTime().before(b)) {
// add another week
cal.add(Calendar.WEEK_OF_YEAR, 1);
weeks++;
}
return weeks;
}
public static Date resetTime (Date d) {
Calendar cal = new GregorianCalendar();
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
Calendar a = new GregorianCalendar(2002,1,22);
Calendar b = new GregorianCalendar(2002,1,28);
System.out.println(a.get(Calendar.WEEK_OF_YEAR));
System.out.println(b.get(Calendar.WEEK_OF_YEAR));
int weeks = b.get(Calendar.WEEK_OF_YEAR)-a.get(Calendar.WEEK_OF_YEAR);
System.out.println(weeks);
попробуй это, должно работать
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2007, 01, 10);
calendar2.set(2007, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int diffWeeks = (int)diff / (7*24 * 60 * 60 * 1000);
java.время
на java.время framework встроен в Java 8 и более поздние версии. Эти новые классы вытесняют старые классы даты и времени в комплекте с самыми ранними версиями Java. Эти классы также вытесняют весьма успешные Joda Времени рамки, и построены теми же людьми, в том числе во главе с Стивен Colbourne.
ThreeTen-Extra
на ThreeTen-Extra - это официальное расширение java.время framework, встроенный в Java 8 и более поздние версии. Этот проект является испытательным полигоном для возможных будущих дополнений к java.время и должно быть полезно само по себе.
Weeks
класс
этот проект включает в себя Weeks
класс для представления нескольких недель. Он не только может вычислять, он также предназначен для использования в вашем коде в качестве типа безопасного объекта. Такое использование также помогает сделать ваш код самодокументируемыми.
вы можете создать экземпляр, предоставив пару точек во времени с Weeks.between
метод. Эти моменты времени могут быть чем угодно, реализующим java.время.временной.Темпоральный в том числе Instant
, LocalDate
, OffsetDateTime
, ZonedDateTime
, Year
, YearMonth
и многое другое.
код java.util.Date
объекты можно легко преобразовать к Instant
объекты, моменты на временной шкале в UTC с разрешением в наносекундах. Посмотрите на новые методы, добавленные к старым классам date-time. Для перехода от даты к мгновенному вызову java.util.Date::toInstant
.
Instant start = utilDateStart.toInstant();
Instant stop = utilDateStop.toInstant();
Weeks weeks = Weeks.between( start , stop );
вы можете попросить количество недель. Вы также можете сделать много больше.
int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
о java.время
на java.время framework встроен в Java 8 и позже. Эти классы вытесняют беспокойных старых наследие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
на Joda Времени, теперь режим обслуживания, советует миграцию в java.время классы.
чтобы узнать больше, см. В Oracle Учебник. Поиск переполнения стека много примеров и объяснений. Спецификация JSR 310.
вы можете обменять java.время объекты непосредственно с вашей базой данных. Используйте драйвер JDBC соответствуют JDBC 4.2 или позже. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
где получить java.время занятий?
-
Java SE 8, Java SE 9, Java SE 10, Java SE 11, а позже-часть стандартного API Java с встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
-
Java SE 6 и Java SE 7
- большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
-
Android
- более поздние версии Android bundle реализации java.время классы.
- для более раннего Android (ThreeTenABP проект приспосабливается ThreeTen-Backport (упомянутый выше.) См.как использовать ThreeTenABP....
на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.
взгляните на следующую статью:Java-вычислить разницу между двумя датами
метод daysBetween позволит вам получить количество дней между датами. Затем вы можете просто разделить на 7, чтобы получить количество полных недель.
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(datePicker1.getYear(), datePicker1.getMonth(),
datePicker1.getDayOfMonth());
date2.clear();
date2.set(datePicker2.getYear(), datePicker2.getMonth(),
datePicker2.getDayOfMonth());
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
int week = (dayCount / 7) ;
надеюсь, это может помочь вам
вы можете сделать это следующим образом:
// method header not shown
// example dates:
f = new GregorianCalendar(2009,Calendar.AUGUST,1);
l = new GregorianCalendar(2010,Calendar.SEPTEMBER,1);
DateTime start = new DateTime(f);
DateTime end = new DateTime(l);
// Alternative to above - example dates with joda:
// DateTime start = new DateTime(2009,8,1,0,0,0,0);
// DateTime end = new DateTime(2010,9,1,0,0,0,0);
Interval interval = new Interval(start,end);
int weeksBetween = interval.toPeriod(PeriodType.weeks()).getWeeks();
// return weeksBetween;
Это должно дать вам int, представляющий количество недель между двумя датами.
время Joda вычисляет недели с длительностью двух дат, которые в некоторых случаях могут не соответствовать нашим требованиям. У меня есть метод с Joda Time для вычисления естественных недель между двумя датами. Надеюсь, это поможет вам. Если вы не используете время Joda, вы можете изменить код с календарем, чтобы сделать то же самое.
//Unlike Joda Time Weeks.weeksBetween() that returns whole weeks computed
//from duration, we return natural weeks between two dates based on week of year
public static int weeksBetween(ReadablePartial date1, ReadablePartial date2) {
int comp = date1.compareTo(date2);
if (comp == 0) {
return 0;
}
if (comp > 0) {
ReadablePartial mid = date2;
date2 = date1;
date1 = mid;
}
int year1 = date1.get(DateTimeFieldType.weekyear());
int year2 = date2.get(DateTimeFieldType.weekyear());
if (year1 == year2) {
return date2.get(DateTimeFieldType.weekOfWeekyear()) - date1.get(DateTimeFieldType.weekOfWeekyear());
}
int weeks1 = 0;
LocalDate lastDay1 = new LocalDate(date1.get(DateTimeFieldType.year()), 12, 31);
if (lastDay1.getWeekyear() > year1) {
lastDay1 = lastDay1.minusDays(7);
weeks1++;
}
weeks1 += lastDay1.getWeekOfWeekyear() - date1.get(DateTimeFieldType.weekOfWeekyear());
int midWeeks = 0;
for (int i = year1 + 1; i < year2; i++) {
LocalDate y1 = new LocalDate(i, 1, 1);
int yearY1 = y1.getWeekyear();
if (yearY1 < i) {
y1 = y1.plusDays(7);
midWeeks++;
}
LocalDate y2 = new LocalDate(i, 12, 31);
int yearY2 = y2.getWeekyear();
if (yearY2 > i) {
y2 = y2.minusDays(7);
midWeeks++;
}
midWeeks += y2.getWeekOfWeekyear() - y1.getWeekOfWeekyear();
}
int weeks2 = 0;
LocalDate firstDay2 = new LocalDate(date2.get(DateTimeFieldType.year()), 1, 1);
if (firstDay2.getWeekyear() < firstDay2.getYear()) {
firstDay2 = firstDay2.plusDays(7);
weeks2++;
}
weeks2 += date2.get(DateTimeFieldType.weekOfWeekyear()) - firstDay2.getWeekOfWeekyear();
return weeks1 + midWeeks + weeks2;
}
int startWeek = c1.get(Calendar.WEEK_OF_YEAR);
int endWeek = c2.get(Calendar.WEEK_OF_YEAR);
int diff = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
int deltaYears = 0;
for(int i = 0;i < diff;i++){
deltaYears += c1.getWeeksInWeekYear();
c1.add(Calendar.YEAR, 1);
}
diff = (endWeek + deltaYears) - startWeek;
включает годовые различия. Это сработало для меня:)
private int weeksBetween(Calendar startDate, Calendar endDate) {
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
int start = (int)TimeUnit.MILLISECONDS.toDays(
startDate.getTimeInMillis())
- startDate.get(Calendar.DAY_OF_WEEK);
int end = (int)TimeUnit.MILLISECONDS.toDays(
endDate.getTimeInMillis());
return (end - start) / 7;
}
если этот метод возвращает 0, они находятся в той же неделе
если этот метод возвращает 1 endDate через неделю после startDate
если этот метод возвращает -1 endDate за неделю до startDate
идея
Если вы хотите точное количество полных недель, используйте метод ниже, где конечная дата является эксклюзивной:
public static long weeksBetween(Date date1, Date date2) {
return WEEKS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
}
Если вы хотите версию ceil этого, используйте ниже:
public static long weeksBetween(Date date1, Date date2) {
long daysBetween = DAYS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) + 1;
return daysBetween / 7 + (daysBetween % 7 == 0 ? 0 : 1);
}