按天拆分java.util.Date集合

时间:2015-02-18 07:17:18

标签: java date

请帮助我。我无法弄清楚算法。

我有一个已排序的Dates集合,例如ArrayList,如下所示:

Wed Jan 22 00:00:00 MSK 2014
Wed Jan 22 00:30:00 MSK 2014
Wed Jan 23 01:00:00 MSK 2014
Wed Jan 23 01:30:00 MSK 2014
Wed Jan 23 02:00:00 MSK 2014
Wed Jan 24 02:30:00 MSK 2014
Wed Jan 24 03:00:00 MSK 2014
Wed Jan 24 03:30:00 MSK 2014
Wed Jan 24 04:00:00 MSK 2014
Wed Jan 28 04:30:00 MSK 2014
Wed Jan 28 05:00:00 MSK 2014

我需要此列表的另一个版本,按天分组(从00:00:00到23:59:59),因此它可能是一组列表,如List<List<Date>>。在示例之后,它应该是大小为4的列表,第二个Object ==

List<Date> {Wed Jan 23 01:00:00 MSK 2014;
Wed Jan 23 01:30:00 MSK 2014;
Wed Jan 23 02:00:00 MSK 2014; }

似乎是一件容易的事。但我找不到方便的方法来解决它。提前谢谢。

更新 根据TEXHIK的回答,宽度JDK 7可以这样做:

 public List<List<Date>> split(List<Date> value) {
        List<List<Date>> result = new ArrayList<>();

        int day = value.iterator().next().getDate();
        List<Date> newListEntry = new ArrayList<>();

        for (Date date : value) {
            if (date.getDate() == day) {
                newListEntry.add(date);
            }
            else {
                day = date.getDate();
                result.add(newListEntry);
                newListEntry = new ArrayList<>();
                newListEntry.add(date);
            }
        }
        result.add(newListEntry);//because the last sublist was not added

        return result;
    }

没关系,除非它是java.util.Date的弃用方法。很高兴看到使用Java 8或Joda Time的答案。

5 个答案:

答案 0 :(得分:1)

如果您对UTC时代感到满意,生活会变得更加简单:

  • 毫秒 - 自从unix-epoch开始于一天的边界,所以你可以分开
  • 每天都是24小时,这在很多情况下很方便(例如,如果您正在对数据进行分析)

在这种情况下,您可以使用以下内容:

long millisPerDay = TimeUnit.DAYS.toMillis(1);
Map<Long, List<Date>> datesByDay = new HashMap<>();
for (Date date : dates) {
    long day = date.getTime() / millisPerDay;
    List<Dates> dayDates = datesByDay.get(day);
    if (dayDates == null) {
        dayDates = new ArrayList<>();
        datesByDay.put(day, dayDates);
    }
    dayDates.add(date);
}

当然,Multimap,例如来自Guava,将使这更简单:

long millisPerDay = TimeUnit.DAYS.toMillis(1);
Multimap<Long, Date> datesByDay = ArrayListMultimap.create();
for (Date date : dates) {
    long day = date.getTime() / millisPerDay;
    datesByDay.put(day, date);
}

答案 1 :(得分:0)

尝试填写新的列表,直到这一天等于。由于您的原始列表已排序,因此应该没有错误。

int day;
List<Date> newListEntry = new ArrayList<Date>();
Iterator sourceIterator = your_original_list.iterator();
while(iterator.hasNext())
{
    Date date = iterator.next();
    if (date.getDate() == day)
       newListEntry.add(date);
    else
    {
       day = date.getDate();
       your_new_list.add(newListEntry);
       newListEntry = new ArrayList<Date>();
       newListEntry.add(date);
    }
}
your_new_list.add(newListEntry);//because the last sublist was not added

答案 2 :(得分:0)

public class SortBydate {

public static void main(String args[])
{
    ArrayList<Date> ls = new ArrayList<Date>();
    HashMap<String , ArrayList<Date>> has = new HashMap<String , ArrayList<Date>>();


      SimpleDateFormat format1=new SimpleDateFormat("dd/MM/yyyy/HH/mm/ss");
      try {
          ls.add(format1.parse("22/01/2014/00/00/00"));
          ls.add(format1.parse("22/01/2014/00/30/00"));
          ls.add(format1.parse("23/01/2014/01/00/00"));
          ls.add(format1.parse("23/01/2014/01/30/00"));
          ls.add(format1.parse("23/02/2014/02/00/00"));
          ls.add(format1.parse("24/02/2014/02/30/00"));

          ls.add(format1.parse("24/02/2014/03/00/00"));
          ls.add(format1.parse("24/02/2014/03/30/00"));
          ls.add(format1.parse("24/02/2014/04/00/00"));
          ls.add(format1.parse("28/02/2014/05/00/00"));
          ls.add(format1.parse("28/02/2014/00/30/00"));

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


    Iterator<Date> it = ls.listIterator();

    while(it.hasNext())
    {
        Date dt = it.next();
        String date = dt.getDate() +"," + dt.getMonth() + "," + dt.getYear();

        if(has.containsKey(date))
        {
            has.get(date).add(dt);
        }
        else
        {
            has.put(date, new ArrayList());
            has.get(date).add(dt);
        }

    }

    Set set = has.entrySet();
    it = set.iterator();

    while(it.hasNext())
    {
        Map.Entry entry = (Map.Entry)it.next();

        System.out.println(entry.getValue());
    }

}

}

答案 3 :(得分:0)

  

很高兴看到使用Java 8或Joda Time的答案。

我会使用Java 8 Time LibraryGoogle Guava's Multimap

的混合物
List<LocalDateTime> list=new ArrayList<LocalDateTime>();
// Add the Sorted LocalDateTime into it ...........

Multimap<Integer, LocalDateTime> builder=ArrayListMultimap.create();
list.forEach(local -> builder.put(local.getDayOfMonth(),local));

现在只需迭代Multimap并查看所需的输出

Set keySet = builder.keySet();
Iterator keyIterator = keySet.iterator();
while (keyIterator.hasNext() ) {
    Integer key = (Integer)keyIterator.next();
    List values=(List) builder.get(key);
    System.out.println(values);
}

输入

2015-02-18T16:33:49.114
2015-02-18T17:33:49.114
2015-02-18T18:33:49.114
2015-02-18T19:33:49.114
2015-02-18T20:33:49.114
2015-02-19T17:33:49.114
2015-02-19T18:33:49.114
2015-02-19T19:33:49.114
2015-02-19T20:33:49.114

<强>输出:

[2015-02-18T16:33:49.114,
 2015-02-18T17:33:49.114,
 2015-02-18T18:33:49.114,
 2015-02-18T19:33:49.114,
 2015-02-18T20:33:49.114]

[2015-02-19T17:33:49.114,
2015-02-19T18:33:49.114, 
 2015-02-19T19:33:49.114,
 2015-02-19T20:33:49.114]

答案 4 :(得分:0)

从Java 8的角度来看,这个答案可能很有趣。此示例使用流API以及java.time.*

  public static List<List<Date>> split(List<Date> value) {
    return new ArrayList<>(value.stream().sorted().collect(
        Collectors.groupingBy(
            // Group by LocalDate converted from Date
            d -> d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
            // Group into a LinkedHashMap to preserve encounter order
            LinkedHashMap::new,
            // We want the grouped elements in a List
            Collectors.toList())).values());
  }

以下是相同的单元测试:

  @Test
  public void testSplit() {
    final int TEST_DAYS = 9;
    final int TEST_HOUR_STEP = 8;
    final int TEST_DATES_PER_DAY = 24 / TEST_HOUR_STEP;

    // Generate test data
    List<Date> dateList = new ArrayList<>();
    final int yy = 2015;
    final int mm = 2;
    for (int dd = 1; dd < 1 + TEST_DAYS; ++dd) {
      for (int h = 0; h < 24; h += TEST_HOUR_STEP) {
        LocalDateTime ldt = LocalDateTime.of(yy, mm, dd, h, 0, 0);
        dateList.add(Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()));
      }
    }
    List<List<Date>> splitDates = split(dateList);

    // We should have TEST_DAYS lists
    assertEquals(TEST_DAYS, splitDates.size());

    for (List<Date> ld : splitDates) {
      // Each list should have TEST_DATES_PER_DAY elements
      assertEquals(TEST_DATES_PER_DAY, ld.size());

      // Each list should have a single distinct element when converted to LocalDate
      assertEquals(1, ld.stream()
          .map(d -> d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
          .distinct()
          .count());
    }
  }