0

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:

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
Georgi Koemdzhiev
  • 11,421
  • 18
  • 62
  • 126
  • 1
    For weekly view you can club the same activities and show the activites with their time frame or whatever you have .. and for references you can take a look at Google Fit app or Mi Fit app .. – shadygoneinsane Mar 09 '17 at 09:18
  • @shadygoneinsane Thank you for your suggestion. This is the bit I cannot figure out how to do - how to construct an individual week out of list of dates. I edited it my question with this example since it was not very clear. – Georgi Koemdzhiev Mar 09 '17 at 13:39

4 Answers4

1
/**
 * 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;
}
Jameson
  • 6,400
  • 6
  • 32
  • 53
  • Thank you for the answer. However, I am after something else. My question was more about how do you distinguish an individual week from list of dates. For example, the list of Dates are for the last 50 days (one date per day) how would you construct a List of Dates that would represent one week? – Georgi Koemdzhiev Mar 09 '17 at 13:12
  • I changed my question so it does include this example. I think that mose of the down votes are from people who could not understand what I was asking – Georgi Koemdzhiev Mar 09 '17 at 13:15
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

week view

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 :)

shadygoneinsane
  • 2,226
  • 1
  • 24
  • 47
  • Hi! Thank you for your answer! As you correctly understood me, my plan is to sum up the activities (e.g. walking, running) for all of the dates for each week. However, I am still not sure how to do the date to week separation using Java code. – Georgi Koemdzhiev Mar 09 '17 at 20:34
  • @GeorgiKoemdzhiev updated some more in my answer .. do let me know if you need anymore help with this :) – shadygoneinsane Mar 10 '17 at 09:51
  • Thank you for the answer! I will test it when i get home :) – Georgi Koemdzhiev Mar 10 '17 at 19:49
  • I am accepting your answer since it pointed me to a direction of solving the problem. – Georgi Koemdzhiev Mar 11 '17 at 07:50
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Apr 30 '18 at 21:31
1

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 );
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thank you for the detailed answer. By "Week" I mean a UK time zone week, where each week starts from Monday. I updated the question with an example of the UI design that I am trying to achieve – Georgi Koemdzhiev Mar 09 '17 at 22:55
  • @GeorgiKoemdzhiev (A) So is your definition of week the same as ISO 8601? I have asked twice now, and you have yet to fully define your week. There are crucial subtleties here that you seem to be ignoring. (B) Also, your user-interface is irrelevant. You need to track your data objects by week, hence two Answers talking about using a `Map`, here I suggest using the `YearWeek` object as the “key” to your `Map`. The “value” of the `Map` should be either your data summary or a `Collection` (such as `List`) of your individual data objects. – Basil Bourque Mar 10 '17 at 03:20
  • Apologies for not mentioning what is a "week" in my case. I think ISO 8601 standard week would be fine. You mentioned solving my problem using a Map but how would you check if a date is part of a specific week in the month? – Georgi Koemdzhiev Mar 10 '17 at 07:38
  • 1
    @GeorgiKoemdzhiev You never said anything about Week-of-month in your Question. – Basil Bourque Mar 10 '17 at 11:17
  • I didn't because I am not sure if that approach will work in my case. It just mk sense to use the week of month integer as a key in the hashmap – Georgi Koemdzhiev Mar 10 '17 at 20:44
0

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

Georgi Koemdzhiev
  • 11,421
  • 18
  • 62
  • 126