Получить количество недель между двумя датами. - PullRequest
19 голосов
/ 01 апреля 2012

Я работаю в проекте, и у меня есть два типа в Date. Я хочу рассчитать количество недель между этими двумя датами. Даты могут быть в разные годы. Есть ли хорошее решение для этого?

Я попытался реализовать это с 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();
}

Но это совершенно неправильно ... есть предложения?

Ответы [ 13 ]

32 голосов
/ 01 апреля 2012

Это довольно легко с йодой :

DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);

int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();
25 голосов
/ 19 сентября 2014

Обновление ответа на аккаунт для 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);
}
8 голосов
/ 12 ноября 2013

Использование арифметики даты в 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();
}
2 голосов
/ 01 апреля 2012
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);
1 голос
/ 19 мая 2016

java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти новые классы вытесняют старые классы даты и времени, включенные в самые ранние версии Java. Эти классы также вытесняют очень успешный Joda-Time фреймворк и создаются теми же людьми, в том числе и во главе с Стивеном Колборном .

ThreeTen-Extra

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

Weeks класс

Этот проект включает в себя Weeks класс для представления количества недель. Он не только может вычислять, он также предназначен для использования в вашем коде как объект, безопасный для типов. Такое использование также помогает сделать ваш код самодокументированным.

Вы можете создать экземпляр, указав пару точек во времени с помощью метода Weeks.between. Этими моментами времени может быть все, что реализует java.time.temporal.Temporal , включая Instant, LocalDate, OffsetDateTime, ZonedDateTime, Year, YearMonth и др.

Ваши java.util.Date объекты могут быть легко преобразованы в Instant объекты, моменты на временной шкале в UTC с разрешением в наносекундах. Посмотрите на новые методы, добавленные к старым классам даты и времени. Для перехода от даты к моменту звоните 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.time

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

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

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Вы можете обмениваться java.time объектами непосредственно с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

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

0 голосов
/ 13 июня 2019

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

private fun calculateNumberOfWeeks() {
    val calendarFrom = Calendar.getInstance()
    calendarFrom.set(Calendar.HOUR_OF_DAY, 0)
    calendarFrom.set(Calendar.MINUTE, 0)
    calendarFrom.set(Calendar.SECOND, 0)
    calendarFrom.set(Calendar.MILLISECOND, 0)

    val calendarTo = Calendar.getInstance()
    calendarTo.add(Calendar.MONTH, months)
    calendarTo.set(Calendar.HOUR_OF_DAY, 0)
    calendarTo.set(Calendar.MINUTE, 0)
    calendarTo.set(Calendar.SECOND, 0)
    calendarTo.set(Calendar.MILLISECOND, 0)

    var weeks = -1
    while (calendarFrom.timeInMillis < calendarTo.timeInMillis) {
        calendarFrom.add(Calendar.DATE, 7)
        weeks++
        Log.d(Constants.LOG_TAG, "weeks $weeks")
    }
}
0 голосов
/ 12 февраля 2018

Если вы хотите точное количество полных недель, используйте метод ниже, где дата окончания является исключительной:

public static long weeksBetween(Date date1, Date date2) {
    return WEEKS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
        date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
  }

Если вы хотите использовать эту версию, используйте ниже:

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);
  }
0 голосов
/ 18 мая 2016
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

вы получите идею

0 голосов
/ 29 января 2015
    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;

Включает разницу по годам.Это сработало для меня:)

0 голосов
/ 10 сентября 2012

Joda Time рассчитывает недели с продолжительностью двух дат, которые в некоторых случаях могут не соответствовать нашим требованиям.У меня есть метод с Joda Time для вычисления натуральных недель между двумя датами.Надеюсь, это поможет вам.Если вы не используете Joda Time, вы можете изменить код с помощью Calendar, чтобы сделать то же самое.

//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;
}
...