HKStatisticsCollectionQuery pulling data for each week of the month - ios

I'm trying to create a chart that displays a month's worth of data vs the past month's data broken up by week.
For example viewing the chart today would show July vs June, there would be 5 points on each graph with the following dates:
June: 1-8, 9-15, 16-22, 23-29, 30
July: 1-8, 9-15, 16-22, 23-29, 30-31
The predicate looks like
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:self.pastStartDate endDate:self.currentEndDate options:HKQueryOptionStrictStartDate];
where self.pastStartDate is the first of last month and self.currentEndDate is the last of the current month.
We then set up the query like so
HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType quantitySamplePredicate:predicate options:HKStatisticsOptionDiscreteAverage anchorDate:self.pastStartDate intervalComponents:self.interval];
So for the month, self.interval.day = 7 is set so that we pull a week's worth of data at every interval. The problem is that this interval is not calendar aware, so it doesn't know that the final data point for the last month should only have 1 day, therefore we are getting some overlap.
We have also tried self.interval.weekOfMonth = 1 but again, the interval does not know which month it is in so this is not working either.
Is there a way to create the interval based on the calendar so that it doesn't include more than the end of the month in a given interval?

Related

Comparing working hours of an entity per day against the date (day of the week and hours) from the device

I would like to compare the working hours per day of an entity, fetched from JSON, against the day and hour information from the device. Related to that, I have two questions:
1) What is the best/right way of saving information of working hours per day for a particular entity in a JSON? I think, its structure should be something like this:
"working_hours": {
"<DAY_OF_THE_WEEK_1>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_2>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_3>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_4>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_5>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_6>":"<WORKING_HOURS>",
"<DAY_OF_THE_WEEK_7>":"<WORKING_HOURS>"
}
Here, I use days of the week as keys in a dictionary. However, I'm not sure what is the best/right way to enter "<DAY_OF_THE_WEEK_N>" and "<WORKING_HOURS>" inside a JSON.
2) After fetching this information, how to compare it against the time information from the device. Basically, I need to check the day of the week and then checking whether the current from the device is within the interval of a particular <WORKING_HOURS>.
For those who ask me whether I'm asking about comparing two numbers: I don't ask about that. I need to know the right format to save working hours in JSON also taking into account the day changes.
Currently, the problem is, when I save a time like 21:00 and transform it to a Date:
let workingHoursEnd = "21:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "H:mm"
dateFormatter.timeZone = TimeZone.autoupdatingCurrent
let dateFromString = dateFormatter.date(from: workingHoursEnd)
I get Jan 1, 2000 at 9:00 PM. The time format is ok, I can change it later, however, what I need is to get the current date (especially, day of the week) because I need to take into account the current day, too.
If you can answer to both questions (or even to one of them), I would appreciate your help.

How to keep track of data over various periods of time (Swift) - Counter/Habit Tracking App

I'm trying to create a simple counter/habit tracking app that allows users to see how many times they've completed a task over a certain amount of time (daily/weekly/monthly/yearly/total).
My question is: what is the best way to track variables over time such that when the user selects a time period, the variable's value can update to reflect that change?
A few examples to clarify what I mean:
A user who initially created a monthly timer to track workouts should be able to switch to a weekly timer and see the data update as needed (there should be fewer in a week than in a month).
A user who has created a daily counter should see the daily counter reset to 0 at midnight each day, with the previous day's value visible to compare.
A user who has created a "total" counter should be able to switch to any time period (daily/weekly/monthly/yearly) and see the counter update as needed.
The UI for my app is basically a custom tableview with the counter number, counter name, and the time period over which the counter number is being tracked. A detail view allows users to add to/subtract from the counter's value.
I have been wracking my brain and Google for a long time, so I'd really appreciate any help!
Each task should have a date. When app needs to query for the average per day/week/month/year you can use a NSPredicate to restrict only the results from a given time period.
For instance, here's a predicate that models the last-week scenario that I have written for an app of mine:
func lastWeekPredicate() -> NSPredicate {
let calendar = NSCalendar.currentCalendar()
let endDate = NSDate()
let startDate = calendar.dateByAddingUnit(.CalendarUnitDay, value: -7, toDate: endDate, options: nil)
return NSPredicate(format: "day >= %# AND day =< %#", argumentArray: [startDate!, endDate!])
}
Let's say you modelled your data with Core Data. Querying with this predicate would give you the results of all the tasks that were completed in the last week. The predicate can be modified to work for days, months, year, or any specified number of days.

How to get start and end dat for week number in objective c

In my iOS app, I have a week number and I need to get the start and end date for that week number.
I'm building an app with which the manager of a company can keep track of the worked hours of staff. These worked hours are processed per day in a custom Registration object.
In this object, the date, begin time, end time and break time are stored and based on those values, the worked hours are calculated.
Then, all Registration objects are stored in a WorkWeek object, containing a week number and an array of registrations. WorkWeek's are constructed based on weeknumbers and run from monday through sunday. In this WorkWeek object, the total worked hours, extra hours and wage are calculated.
Now obviously, I can't reliably calculate extra hours if a Workweek is not a full week that runs from monday through friday. This particularly occurs when the user chooses to get all registrations from a mont from my database. A month does not start on monday and does not end on sunday exactly four weeks later, so i'm dealing with unreliable week object.
Wrapping up
To make sure the information I display in my app is reliable, I need to determine whether a certain week (like week 1 or week 52) contains at least 7 days and, if not, I need to set a bool to FALSE which then triggers a notification to my user.
How can I get the begin and end date of a week based on a weeknumer?
This shows how it could be done:
NSCalendar *cal = [NSCalendar currentCalendar];
// Start of week:
NSDateComponents *comp = [[NSDateComponents alloc] init];
comp.weekday = cal.firstWeekday;
comp.weekOfYear = 1; // <-- fill in your week number here
comp.year = 2015; // <-- fill in your year here
NSDate *startOfWeek = [cal dateFromComponents:comp];
// Add 6 days:
NSDate *endOfWeek = [cal dateByAddingUnit:NSCalendarUnitDay value:6 toDate:startOfWeek options:0];
// Show results:
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateStyle = NSDateFormatterShortStyle;
NSLog(#"%#", [fmt stringFromDate:startOfWeek]);
NSLog(#"%#", [fmt stringFromDate:endOfWeek]);
Some notes:
cal.firstWeekday gives the locale dependent index of the first weekday, e.g.
2 = Monday in Germany, or 1 = Sunday in the U.S. Depending on your needs,
you can also use a constant value here.
It might be necessary to set cal.minimumDaysInFirstWeek, compare
NSDateFormatter reports June 2, 2013 as being in week zero.
The dateByAddingUnit:... method is available in OS X 10.9 or later.
Alternatively, use dateByAddingComponents:....
I have assumed that you use the Gregorian calendar, so that a week has 7 days.
Alternatively, you can add one week and then subtract one day.

Array of times for each day of the week in iOS

I have times that I would like to compare to the current time for each day of the week. From what I've come across, it sounds like the best thing to do would be to have an array for each day of the week with the given times I want. For example:
mondayTimes(2:00:00, 5:00:00, 9:00:00, 14:00:00)
tuesdayTimes(3:00:00, 6:00:00, 10:00:00, 15:00:00)
etc...
I want to find out the given day of the week using the current date, and then depending on what day it is, use the array of times for that given day. Then use the current time to find which time is next in the array.
Basically it is like an "alarm clock" that always has set times for every day of the week.
Do I use NSStrings to populate the dates in each array and convert them so I am able to compare them to the current time? What is the best route to go about this?
Thanks!
To get the current date, use NSDate currentDate = [NSDate date];
Then, to extract the weekday: initialize a NSCalendar of your choice, then call [calendar components:NSWeekdayCalendarUnit fromDate:currentDate];, where calendar is your calendar instance.
This produces a number between 1 and 7 (for the Gregorian calendar) where 1 is Sunday and 7 is Saturday. I would then advise you put all of your times in an array of arrays, with the 1 index containing an array of your sundayTimes, 2 containing an array of mondayTimes, ... 7 containing an array of your saturdayTimes.
Then using [allTimes objectAtIndex weekday] will return a NSArray of your times. All that's left is to compare the times, which I'm sure you can figure out.

same day of last month ios

Is there any way using NSCalender you can get same day of last month?
I am using a calender which shows user 1 month like the iPad calender when they click on the button I want to move to previous month but should select the same day as before.
I want to just do
[components setMonth:([components month] - 1)];
but this will create problems when I are moving from a month with 31 days to month with 30 days and selected day is 31st.
I was able to find examples for android but not iOS.
android example
Any help would be appreciated
Check out this link.
It's about adding one month, but you could probably do the same with subtracting.
Change
[dateComponents setMonth:1];
into
[dateComponents setMonth:-1];
Seems there is no obvious "right" answer and no "built-in" answer.
As Chris's "simple" idea may lead to invalid dates, you may have to handle the edge-cases.
Pseudocode to deal with day-month-year:
if month = December start with day-1-(year-1), else
day-(month-1)-year [using dateComponents]
check if this a valid date (using NSDateFormatter like in this question
repeat subtracting one day until you reach a valid date
Another idea:
prevMonthDate = startDate;
Repeat
prevMonthDate = prevMonthDate - 1 day
Until (Month(prevMonthDate) < Month(startDate) Or Year(prevMonthDate) < Year(startDate))
And (Day(prevMonthDate) <= Day(startDate))
This requires working with NSDate and NSDateComponents, check out the Date and Time Programming Guide.

Resources