Java:如何在相应的一周内对所有Java日期进行分组?

时间:2015-04-29 20:26:09

标签: java date

问题:

我有很多日期,我需要按周安排。

问题: 如何按日期一周对日期进行分组?

示例数据集

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

6 个答案:

答案 0 :(得分:9)

如果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

答案 1 :(得分:4)

您只需使用自定义ListDate 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,但这取决于您

答案 2 :(得分:1)

使用以下代码获取周数:

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

答案 3 :(得分:1)

java.time

与其他答案中的其他几个人一样,我建议您使用 java.time,现代 Java 日期和时间 API,进行日期工作。以下代码具有以下特点:

  • 每周中的日期列表保留日期在原始列表中的顺序,
  • 它处理不同的年份
  • 例如,指定了周方案,因此您可以指定该周是从周日还是周一开始。

我首先声明:

private static Locale weekLocale = Locale.FRANCE;
private static DateTimeFormatter weekFormatter
        = DateTimeFormatter.ofPattern("'Year' Y 'week' w", weekLocale);
private static DateTimeFormatter dateFormatter 
        = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
                .withLocale(Locale.US);

现在的工作是这样的:

    WeekFields wf = WeekFields.of(weekLocale);
    
    List<LocalDate> dates = List.of(
            LocalDate.of(2015, Month.APRIL, 1),
            LocalDate.of(2015, Month.APRIL, 2),
            LocalDate.of(2015, Month.APRIL, 3),
            LocalDate.of(2015, Month.APRIL, 4),
            LocalDate.of(2015, Month.APRIL, 5),
            LocalDate.of(2015, Month.APRIL, 6),
            LocalDate.of(2015, Month.APRIL, 7),
            LocalDate.of(2015, Month.APRIL, 8),
            LocalDate.of(2015, Month.APRIL, 9),
            LocalDate.of(2014, Month.APRIL, 9),
            LocalDate.of(2014, Month.APRIL, 6),
            LocalDate.of(2014, Month.APRIL, 1));
    
    // Group the dates by the first day of the week they are in
    Map<LocalDate, List<LocalDate>> datesByWeek = dates.stream()
            .collect(Collectors.groupingBy(d -> d.with(wf.dayOfWeek(), 1)));
    
    // Print results ordered by week
    datesByWeek.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .forEach(e -> {
                System.out.println(e.getKey().format(weekFormatter));
                e.getValue().forEach(d -> System.out.println(d.format(dateFormatter)));
                System.out.println();
            });

输出为:

<块引用>
Year 2014 week 14
Apr 6, 2014
Apr 1, 2014

Year 2014 week 15
Apr 9, 2014

Year 2015 week 14
Apr 1, 2015
Apr 2, 2015
Apr 3, 2015
Apr 4, 2015
Apr 5, 2015

Year 2015 week 15
Apr 6, 2015
Apr 7, 2015
Apr 8, 2015
Apr 9, 2015

如果您想要美国周数,请更改声明:

private static Locale weekLocale = Locale.US;

输出相应改变:

<块引用>
Year 2014 week 14
Apr 1, 2014

Year 2014 week 15
Apr 9, 2014
Apr 6, 2014

Year 2015 week 14
Apr 1, 2015
Apr 2, 2015
Apr 3, 2015
Apr 4, 2015

Year 2015 week 15
Apr 5, 2015
Apr 6, 2015
Apr 7, 2015
Apr 8, 2015
Apr 9, 2015

2014 年 4 月 6 日和 2015 年 4 月 5 日现在是它们各自年份的第 15 周,因为它们是星期日,而美国周从星期日开始。

如果您总是想要 ISO 周,您可以通过按 YearWeek(来自 ThreeTen Extra 项目的类)分组来编写更优雅的解决方案。链接:YearWeek documentation

答案 4 :(得分:0)

您可以尝试使用此代码按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

答案 5 :(得分:0)

将功能编程的强大功能与Java 8 Streams结合使用,并使用新的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())));

您将获得一个Map,其中关键整数是一年中的周数,该键的值是这些日期属于该weekNumber的日期列表。