How to group list of Dates to corresponding week in Java?

柔情痞子 提交于 2020-01-17 07:21:08

问题


I am working on an Android app that will display a list of activities. Every activity (i.e. waling, running) has a property Date (i.e. 9 March 8:58 2017). I have two buttons on the screen - Daily and Weekly and I want to switch betweren the two and change the list accordingly. Now, for the Daily list, I don't have to change anything, since a new Activity is created for every day.

However, I am not sure how to go about the Weekly list. It will essentially calculate stats (adding up the statistics for the individual weeks).

For example, I have a list of dates for the last 50 days. How to distinguish an individual list of Dates that would represent an individual week so I can construct a list of Weeks? Basically, convert those 50 dates into their week equivalent (e.g. about 7 weeks)

This is a test list of Dates that I am trying to get working first:

HashMap<Integer,Date> dateHashMap = new HashMap<>();

    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    List<Date> dates = new ArrayList<>();


    dates.add(sdf.parse("10/03/2017"));
    dates.add(sdf.parse("9/03/2017"));
    dates.add(sdf.parse("8/03/2017"));
    dates.add(sdf.parse("7/03/2017"));
    dates.add(sdf.parse("6/03/2017"));

    dates.add(sdf.parse("23/02/2017"));
    dates.add(sdf.parse("3/02/2017"));

    dates.add(sdf.parse("2/02/2017"));
    dates.add(sdf.parse("1/02/2017"));


    for(Date d:dates){

        dateHashMap.put(d.getDay(),d);
    }

    System.out.println(dateHashMap.toString());

An example UI design that I am trying to achieve:


回答1:


As you already have Date property for each activity, then its quite simple actually

First just decide how you want your weeks
ex: I would just go from Mon to Sun as one week

So here Week nth will have dates - 1st to 5th March
and Week nth+1 will have 6th to 12th March and so on.. and as far as i can understand you already have every activity (i.e. waling, running) with a property Date (i.e. 9 March 8:58 2017)

So taking an example here (let me know if this isn't how you have your data) :
waling - 1 March 2017 8:58 to 9:58, 3 March 2017 6:20 to 6:50, 8 March 2017 12:00 to 13:00


running - 2 March 2017 6:10 to 8:00, 3 2017 March 7:00 to 8:00, 9 March 2017 5:50 to 7:00


Now data for Week nth you can calculate by adding up duration for waling activity for dates 1st and 3rd March as waling was present only on these dates on Week nth of March 2017 and similarly for week nth+1 and so on
Same goes for running activity for week nth adding up for dates 2nd March, 3rd March and similarly for week nth+1 and so on..

Now you will have something like :

Week nth :

  • Wailing - 1 hr and 30 min
  • Running - 2 hrs and 50 min

Week nth+1 :

  • Wailing - 1 hr
  • Running - 1 hr and 10 min


    And on clicking of each activity you can show some more details..
    Hope this helps :)

    Edit :
    Considering this is how you have your dates list

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

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

    try {
        dates.add(sdf.parse("10/03/2017"));
        dates.add(sdf.parse("9/03/2017"));
        dates.add(sdf.parse("8/03/2017"));
        dates.add(sdf.parse("7/03/2017"));
        dates.add(sdf.parse("6/03/2017"));
        dates.add(sdf.parse("23/02/2017"));
        dates.add(sdf.parse("3/02/2017"));
        dates.add(sdf.parse("2/02/2017"));
        dates.add(sdf.parse("1/02/2017"));
    } catch (ParseException e) {
        e.printStackTrace();
    }

You can create a custom List just to identify the dates that falls in the same week
ex (I just used what @Jameson suggested in his answer, you can always write this a lot better):

public List<WeekDay> getListOfWeeksFromListOfDates(List<Date> listOfDates) {
    List<WeekDay> listOfWeeks = new ArrayList<>();
    WeekDay weekDay;
    for (Date date : listOfDates) {
        weekDay = new WeekDay(date, new SimpleDateFormat("w").format(date));
        listOfWeeks.add(weekDay);
    }

    return listOfWeeks;
}


public class WeekDay {

    Date date;
    String weekIdentifier;

    public WeekDay(Date Date, String WeekIdentifier) {
        this.date = Date;
        this.weekIdentifier = WeekIdentifier;
    }

    public Date getDate() {
        return date;
    }

    public String getWeekIdentifier() {
        return weekIdentifier;
    }

}

And you can use getListOfWeeksFromListOfDates(dates); to have a list with Dates and Week number, this week number can serve as an identifier to compare the dates and then you can add the activities for dates with same Week number..
Hope you are getting what i am trying to convey here :)




回答2:


/**
 * Gets a list of week numbers (as strings) from a list of dates.
 *
 * @param listOfDates the list of dates
 * @return a list of week in year (as string), corresponding
 *         one-to-one to the values in the input list.
 */
public List<String> getListOfWeeksFromListOfDates(List<Date> listOfDates) {
    List<String> listOfWeeks = new ArrayList<>();

    for (Date date : listOfDates) {
        listOfWeeks.add(new SimpleDateFormat("w").format(date));
    }

    return listOfWeeks;
}



回答3:


Week?

You have not defined what you mean by week.

  • Do you mean the standard ISO 8601 week where each week starts on a Monday and week # 1 contains the first Thursday, each week numbered 1-52 or 53?
  • Or do you mean a United States type week beginning on a Sunday with weeks numbered 1-52/53 starting with January 1, and if so are the last days of the previous week in the previous year or the new year?
  • Or do you mean something else?

Time zone?

What time zone do want to use as the context for determining the date? Or do you want to keep your date-times in UTC like Stack Overflow does in tracking your activity for “today” vs “yesterday”?

Avoid legacy date-time classes

The troublesome old date classes including Date and Calendar should be avoided whenever possible. They are now supplanted by the java.time classes.

Convert your given Date objects to Instant, a moment on the timeline in UTC.

Instant instant = myDate.toInstant();

ISO 8601

I suggest using the standard week whenever possible.

Adjust your Instant into the desired time zone.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

Retrieve the standard week number.

int weekNumber = zdt.get( WeekFields.ISO.weekOfWeekBasedYear() );

Keep in mind that the year number to go with this week number is not the calendar year. We want the year of the week-based year. For example, in some years, December 30 and 31 can belong to the following year number of a week-based year.

int yearOfWeekBasedYear = zdt.get( WeekFields.ISO.weekBasedYear() );

You could track your records against a string composed of this yearOfWeekBasedYear and weekNumber. Use standard format, yyyy-Www such as 2017-W07.

ThreeTen-Extra YearWeek

Instead I suggest you use meaningful objects rather than mere strings. Add the ThreeTen-Extra library to your project to gain the YearWeek class.

This code replaces the WeekFields code we did above.

YearWeek yw = YearWeek.from( zdt );



回答4:


Thanks to @shadygoneinsane and @ Basil Bourque for pointing me to the right direction I solved the problem the following way:

TreeMap<Integer, List<Date>> dateHashMap = new TreeMap<>();

    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    List<Date> dates = new ArrayList<>();


    dates.add(sdf.parse("10/03/2017"));
    dates.add(sdf.parse("9/03/2017"));
    dates.add(sdf.parse("8/03/2017"));
    dates.add(sdf.parse("7/03/2017"));
    dates.add(sdf.parse("6/03/2017"));

    dates.add(sdf.parse("23/02/2017"));
    dates.add(sdf.parse("3/02/2017"));

    dates.add(sdf.parse("2/02/2017"));
    dates.add(sdf.parse("1/02/2017"));


    for (int i = 0; i < dates.size(); i++) {
        List<Date> datesList = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dates.get(i));

        int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);

        for (Date date : dates) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            if (weekOfMonth == c.get(Calendar.WEEK_OF_MONTH)) {
                datesList.add(date);
            }
        }

        dateHashMap.put(weekOfMonth, datesList);


    }

    System.out.println(dateHashMap.toString());
}

And the result:

Output:

1=[Fri Feb 03 00:00:00 GMT 2017,
 Thu Feb 02 00:00:00 GMT 2017,
 Wed Feb 01 00:00:00 GMT 2017],
 2=[Fri Mar 10 00:00:00 GMT 2017,
 Thu Mar 09 00:00:00 GMT 2017,
 Wed Mar 08 00:00:00 GMT 2017,
 Tue Mar 07 00:00:00 GMT 2017,
 Mon Mar 06 00:00:00 GMT 2017],
 4=[Thu Feb 23 00:00:00 GMT 2017]

Exactly what I needed! So now I can iterate through each week and sum up the statistics and thus formulate the "Weekly" view of the list



来源:https://stackoverflow.com/questions/42690985/how-to-group-list-of-dates-to-corresponding-week-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!