Java: как мне сгруппировать все даты java в соответствующую неделю?



Задача:



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

Вопрос:
Как мне сгруппировать даты по неделе года, в котором они находятся?



Пример Набора Данных



Date date = new SimpleDateFormat.parse("04/01/2015")
Date date = new SimpleDateFormat.parse("04/02/2015")
Date date = new SimpleDateFormat.parse("04/03/2015")
Date date = new SimpleDateFormat.parse("04/04/2015")
Date date = new SimpleDateFormat.parse("04/05/2015")
Date date = new SimpleDateFormat.parse("04/06/2015")
Date date = new SimpleDateFormat.parse("04/07/2015")
Date date = new SimpleDateFormat.parse("04/08/2015")
Date date = new SimpleDateFormat.parse("04/09/2015")


Желаемый Выход



HashMap<Date, Date> hashMap = groupByWeek(ArrayList<Date> dates);

printWeeklyGroupedDates();

Week 1:
04/01/2015
04/02/2015
04/03/2015
04/04/2015
04/05/2015
04/06/2015
04/07/2015
Week 2:
04/08/2015
04/09/2015


Что я пробовал



public Date getWhichYearlyWeek(Date date){

Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.get(Calendear.WEEK_OF_YEAR);

//Need to return this as 'Date' but indicate which week this is for the TreeMap functionality below

return cal.getTime();
}


public TreeMap<Date, ArrayList<Date>> getWeeklyMappedDates(ArrayList<Date> dateArray){

TreeMap<Date, ArrayList<Date>> treeMap = new TreeMap<Date, ArrayList<Date>>

for(Date i : dateArray){

Date date = getWhichYearlyWeek(date);

if(!treeMap.containsKey(date))
treeMap.get(date).add(date);
else
treeMap.put(date, new ArrayList<Date>());
}

return treeMap;
}
541   7  

7 ответов:

Вы можете просто отсортировать List из Date s, используя пользовательский Comparator. Следующий пример сортирует даты по неделям года, а затем по датам, не знаю, хотите ли вы вторую часть, но это хорошая демонстрация...

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
            List<Date> dates = new ArrayList<Date>(25);
            dates.add(sdf.parse("04/01/2015"));
            dates.add(sdf.parse("04/02/2015"));
            dates.add(sdf.parse("04/03/2015"));
            dates.add(sdf.parse("04/04/2015"));
            dates.add(sdf.parse("04/05/2015"));
            dates.add(sdf.parse("04/06/2015"));
            dates.add(sdf.parse("04/07/2015"));
            dates.add(sdf.parse("04/08/2015"));
            dates.add(sdf.parse("04/09/2015"));

            int week = 0;
            int woy = -1;
            Collections.sort(dates, new WeekComparator());
            for (Date date : dates) {
                if (woy != getWeekOfYear(date)) {
                    woy = getWeekOfYear(date);
                    week++;
                    System.out.println("Week " + week + ":");
                }
                System.out.println(date);
            }

        } catch (ParseException exp) {
            exp.printStackTrace();
        }
    }

    public static class WeekComparator implements Comparator<Date> {

        @Override
        public int compare(Date o1, Date o2) {
            int result = getWeekOfYear(o1) - getWeekOfYear(o2);
            if (result == 0) {
                result = o1.compareTo(o2);
            }
            return result;
        }

    }

    protected static int getWeekOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.WEEK_OF_YEAR);
    }

}

Который выводит

Week 1:
Wed Apr 01 00:00:00 EST 2015
Thu Apr 02 00:00:00 EST 2015
Fri Apr 03 00:00:00 EST 2015
Sat Apr 04 00:00:00 EST 2015
Week 2:
Sun Apr 05 00:00:00 EST 2015
Mon Apr 06 00:00:00 EST 2015
Tue Apr 07 00:00:00 EST 2015
Wed Apr 08 00:00:00 EST 2015
Thu Apr 09 00:00:00 EST 2015

Java 8 Time API

И только потому, что мне нужна практика...

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

public class Test {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/yyyy");

        List<LocalDate> dates = new ArrayList<LocalDate>(25);
        dates.add(LocalDate.parse("04/01/2015", dtf));
        dates.add(LocalDate.parse("04/02/2015", dtf));
        dates.add(LocalDate.parse("04/03/2015", dtf));
        dates.add(LocalDate.parse("04/04/2015", dtf));
        dates.add(LocalDate.parse("04/05/2015", dtf));
        dates.add(LocalDate.parse("04/06/2015", dtf));
        dates.add(LocalDate.parse("04/07/2015", dtf));
        dates.add(LocalDate.parse("04/08/2015", dtf));
        dates.add(LocalDate.parse("04/09/2015", dtf));

        int week = 0;
        int woy = -1;
        Collections.sort(dates, new WeekComparator());
        for (LocalDate date : dates) {
            if (woy != getWeekOfYear(date)) {
                woy = getWeekOfYear(date);
                week++;
                System.out.println("Week " + week + ":");
            }
            System.out.println(date);
        }
    }

    public static class WeekComparator implements Comparator<LocalDate> {

        @Override
        public int compare(LocalDate o1, LocalDate o2) {
            int result = getWeekOfYear(o1) - getWeekOfYear(o2);
            if (result == 0) {
                result = o1.compareTo(o2);
            }
            return result;
        }

    }

    protected static int getWeekOfYear(LocalDate date) {
        WeekFields wf = WeekFields.of(Locale.getDefault());
        return date.get(wf.weekOfYear());
    }

}

Который выводит

Week 1:
2015-04-01
2015-04-02
2015-04-03
2015-04-04
Week 2:
2015-04-05
2015-04-06
2015-04-07
2015-04-08
2015-04-09

В любом случае вы можете сопоставить каждую из дат в Map, настроенную по неделе, но это зависит от вас

Если бы Java 8 была доступна:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
TemporalField weekOfYear = WeekFields.of(Locale.getDefault()).weekOfYear();

Stream.of(
      "04/01/2015"
    , "04/02/2015"
    , "04/03/2015"
    , "04/04/2015"
    , "04/05/2015"
    , "04/06/2015"
    , "04/07/2015"
    , "04/08/2015"
    , "04/09/2015"
)
.collect(Collectors.groupingBy(
    d -> LocalDate.parse(d, formatter).get(weekOfYear),
    LinkedHashMap::new,
    Collectors.toList()
))
.forEach((week, dates) -> {
    System.out.println("Week " + week + ":");

    dates.forEach(System.out::println);
});

Эта печать (с использованием локали de_CH на моем компьютере)

Week 14:
04/01/2015
04/02/2015
04/03/2015
04/04/2015
04/05/2015
Week 15:
04/06/2015
04/07/2015
04/08/2015
04/09/2015

Используйте код ниже, чтобы получить номер недели:

public static int getWeek(Date date) {
  Calendar cal = Calendar.getInstance();
  cal.setTime(date);
  return cal.get(WEEK_OF_YEAR);
}

Поскольку вы упомянули, что вам нужно вернуть дату, попробуйте использовать Calendar#clear() , а затем Calendar#setTime(Date), а затем использовать Calendar#get(календарь.НЕДЕЛЬ-ЛЕТ).

Поскольку #getWhichYearlyWeek(Date) теперь является избыточным, вы можете пропустить его вообще.

For не может работать так, как вы его реализовали, вот некоторые исправления:

for (Date i : dateArray) {
  Date date = getWhichYearlyWeek(date);
  if(treeMap.containsKey(date))
    treeMap.get(date).add(i);
  else {
    ArrayList<Date> al = new ArrayList<Date>();
    al.add(i);
    treeMap.put(date, al);
  }
}
  1. Если бы не было, но этого не должно быть
  2. Вы добавили неделю вместо даты
  3. Вы забыли добавить дату в пустой список ArrayList

Использовать GregorianCalendar:

public Date getWhichYearlyWeek(Date date) {
  GregorianCalendar cal = new GregorianCalendar();
  cal.setTime(date);
  // (*) = remove if you are only dealing with real dates and not dateTime
  cal.set(Calendar.HOUR_OF_DAY, 0); // (*)
  cal.clear(Calendar.MINUTE); // (*)
  cal.clear(Calendar.SECOND); // (*)
  cal.clear(Calendar.MILLISECOND); // (*)
  cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); // or Calendar.MONDAY
  return cal.getTime();
}

Вы можете попробовать этот код для группировки дат по WEEK_OF_YEAR.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GroupByWeekSampleCode {

    /**
     * @param year
     * @param weekOfYear
     * @return a unique hashcode generated from year and week of year
     */
    public static int getYearWeekOfYearHashCode(int year, int weekOfYear) {
        int result = (int) (((float) year + ((float) weekOfYear / 100)) * 100);
        return result;
    }

    /**
     * @param hashCode
     * @return the week of year from this hash code
     */
    public static int getWeekOfYearFromHashCode(int hashCode) {
        int year = (int) hashCode / 100;
        int weekOfYear = (int) (hashCode % year);
        return weekOfYear;
    }

    /**
     * @param hashCode
     * @return year from this hash code
     */
    public static int getYearFromHashCode(int hashCode) {
        int year = (int) hashCode / 100;
        return year;
    }

    public static void main(String[] args) {

        try {

            List<Date> datesToGroup = new ArrayList<Date>();

            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
            datesToGroup.add(sdf.parse("04/01/2015"));
            datesToGroup.add(sdf.parse("04/02/2015"));
            datesToGroup.add(sdf.parse("04/03/2015"));
            datesToGroup.add(sdf.parse("04/04/2015"));
            datesToGroup.add(sdf.parse("04/05/2015"));
            datesToGroup.add(sdf.parse("04/06/2015"));
            datesToGroup.add(sdf.parse("04/07/2015"));
            datesToGroup.add(sdf.parse("04/08/2015"));
            datesToGroup.add(sdf.parse("04/09/2015"));

            datesToGroup.add(sdf.parse("12/27/2015"));
            datesToGroup.add(sdf.parse("12/28/2015"));
            datesToGroup.add(sdf.parse("12/29/2015"));
            datesToGroup.add(sdf.parse("12/30/2015"));
            datesToGroup.add(sdf.parse("12/31/2015"));
            datesToGroup.add(sdf.parse("01/01/2016"));
            datesToGroup.add(sdf.parse("01/02/2016"));
            datesToGroup.add(sdf.parse("01/03/2016"));
            datesToGroup.add(sdf.parse("01/04/2016"));

            final Map<Integer, List<Date>> groupedDatesByWeekOfYear = new HashMap<Integer, List<Date>>() {

                private static final long serialVersionUID = 1L;

                @Override
                public List<Date> get(Object key) {
                    List<Date> list = super.get(key);
                    if (list == null) {
                        list = new ArrayList<Date>();
                        super.put((Integer) key, list);
                    }
                    return list;
                }
            };

            for (Date date : datesToGroup) {
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);

                Calendar previousYearLastDate = Calendar.getInstance();
                previousYearLastDate.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
                previousYearLastDate.set(Calendar.MONTH, 11);
                previousYearLastDate.set(Calendar.DAY_OF_MONTH,
                        previousYearLastDate.getActualMaximum(Calendar.DAY_OF_MONTH));

                // a hash code generated from year and week of year value
                int yearWeekOfYearHashCode = 0;

                // to check if some of the dates in this week of year comes
                // in previous year last month, if true then the previous year
                // should be taken to generate hash code
                if (cal.get(Calendar.MONTH) == 0
                        && cal.get(Calendar.WEEK_OF_YEAR) == previousYearLastDate.get(Calendar.WEEK_OF_YEAR)) {
                    yearWeekOfYearHashCode = getYearWeekOfYearHashCode(previousYearLastDate.get(Calendar.YEAR),
                            previousYearLastDate.get(Calendar.WEEK_OF_YEAR));
                } else {
                    yearWeekOfYearHashCode = getYearWeekOfYearHashCode(cal.get(Calendar.YEAR),
                            cal.get(Calendar.WEEK_OF_YEAR));
                }

                groupedDatesByWeekOfYear.get(yearWeekOfYearHashCode).add(date);
            }

            for (Integer yearWeekOfYearHashCode : groupedDatesByWeekOfYear.keySet()) {
                System.out.println("year=" + getYearFromHashCode(yearWeekOfYearHashCode) + ", weekOfYear="
                        + getWeekOfYearFromHashCode(yearWeekOfYearHashCode) + ", dates under this week ");

                List<Date> datesInThisWeek = groupedDatesByWeekOfYear.get(yearWeekOfYearHashCode);
                for (Date date : datesInThisWeek) {
                    System.out.println(date);
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);
                }
                System.out.println();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

Это выведет

year=2015, weekOfYear=1, dates under this week 
Sun Dec 27 00:00:00 IST 2015
Mon Dec 28 00:00:00 IST 2015
Tue Dec 29 00:00:00 IST 2015
Wed Dec 30 00:00:00 IST 2015
Thu Dec 31 00:00:00 IST 2015
Fri Jan 01 00:00:00 IST 2016
Sat Jan 02 00:00:00 IST 2016

year=2015, weekOfYear=14, dates under this week 
Wed Apr 01 00:00:00 IST 2015
Thu Apr 02 00:00:00 IST 2015
Fri Apr 03 00:00:00 IST 2015
Sat Apr 04 00:00:00 IST 2015

year=2015, weekOfYear=15, dates under this week 
Sun Apr 05 00:00:00 IST 2015
Mon Apr 06 00:00:00 IST 2015
Tue Apr 07 00:00:00 IST 2015
Wed Apr 08 00:00:00 IST 2015
Thu Apr 09 00:00:00 IST 2015

year=2016, weekOfYear=2, dates under this week 
Sun Jan 03 00:00:00 IST 2016
Mon Jan 04 00:00:00 IST 2016

Используйте возможности функционального программирования с потоками Java 8 и используйте новый Java Time Api:

Предполагая, что ваши даты находятся в коллекции, например:

List<LocalDate> dates = getMyDates();
 WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY,7);
 Map<Integer, List<LocalDate>> datesGroupedByWeekNumber  = dates.stream()
                    .collect(Collectors.groupingBy(date -> date.get(weekFields.weekOfYear())));

Вы получите карту, где ключевое целое число-это номер недели в году, а значение для этого ключа-список дат, где эти даты принадлежат этому номеру недели.

Comments

    Ничего не найдено.