How to query data from the last 7 days(week) on parse - ios

I am trying to query data from the last 7 days(week) on parse. How could I do that. I have been researching many articles/forums, but they all seem to be outdated.

You'd use something like:
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:604800];
[query whereKey:#"createdAt" lessThan:date];
where 604800 is the number of seconds in a week.

Related

HKStatisticsCollectionQuery pulling data for each week of the month

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?

Querying for a date constraint

I've done research on this question and thought I found the answer which makes sense but it's not working so i'm not sure if I'm making a silly mistake. I want to query for data that is created in the past week, month, year,..etc. I looked at my data already uploaded to parse and to test it out, I wanted to query for the data from the past 5 days. For some reason, it finds 0 objects when there should be five objects created after August 8th. When I switched to lessThanOrEqualTo it found all 9 objects even though there's 4 objects created before August 8th. Any clarity on this. Thanks
NSDate *then=[NSDate dateWithTimeIntervalSinceNow:-7200];
PFQuery *query=[PFQuery queryWithClassName:#"urinationAmount"];
[query whereKey:#"user" equalTo:[PFUser currentUser]];
[query whereKey:#"createdAt" greaterThanOrEqualTo:then];
urinationDataArray=[query findObjects];
NSLog(#"Objects in Array:%i",urinationDataArray.count);
According to Date and Time Programming Guide, you shouldn't manually do calendar calculations.
Quote from the same document says:
NSDate provides the absolute scale and epoch for dates and times, which can then be rendered into a particular calendar for calendrical calculations or user display. To perform calendar calculations, you typically need to get the component elements of a date, such as the year, the month, and the day. You should use the provided methods for dealing with calendrical calculations because they take into account corner cases like daylight savings time starting or ending and leap years.
So five days ago should be something like this:
NSCalendar * currentCalendar = [NSCalendar currentCalendar];
NSDateComponents * dateComponents = [NSDateComponents new];
NSDate * now = [NSDate date];
[dateComponents setDay:-5];//five days ago
NSDate * fiveDaysAgo = [currentCalendar dateByAddingComponents:dateComponents toDate:now options:0];
You can check NSDateComponents Class Reference for further calendar units that you can use for your calculations.
The following code will not give you five days ago:
NSDate *then=[NSDate dateWithTimeIntervalSinceNow:-7200];
You should do:
NSDate *then=[NSDate dateWithTimeIntervalSinceNow:-1 * (86400 * 5)];
There are 86,400 seconds in a 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.

Setting and Retrieving Dates in iOS that avoid issues with timezone changes

I have a "time-tracking" app that allows a user to create an entry on whichever days a user desires but only one permitted per day. I store these entries into CoreData.
[rateObject setValue:[Day dateWithHour:currentDate forHour:12] forKey:#"date"];
Later, I retrieve these entries using the following code.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Day"];
request.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"date" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:#"whoWorked == %# && date => %# && date =< %#", whoWorked, [Day dateWithHour:fromDate forHour:0], [Day dateWithHour:toDate forHour:24]];
As you can see I placed the entry in the middle of the day (12 hours) and retrieved the dates from start of the first day (0 hours) and end of the last day (24 hours).
This is a hack which seems to work when I only shift timezones by a few hours or switch for Standard Time to Daylight Savings. It falls apart when I move from NA to Europe i.e. the entries in the old timezone appear on different days in the retrieval.
What I want to get to is an entry made on April 25, 2014 appears on April 25, 2014 no matter what timezone I am currently in.
I have looked at a number of sources to understand NSDate, NSDateComponents, NSCalendar etc but can't seem to land on a good understanding that will allow me to implement this correctly or cleanly. Any advice appreciated.
Here is my method for creating a date with a specific hour (in Day).
+ (NSDate *)dateWithHour:(NSDate *)date forHour:(int)hour {
// Create and initialize date component instance
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit fromDate:date];
if (hour<0) hour = 0;
else if (hour>24) hour = 24;
[dateComponents setHour:hour];
// Create period dates
NSDate *newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
return newDate;
}
The best to use time-zone and platform independent is the timestamp, which you can get from NSDate as well. With that you can easily do calculations with Time-intervals. If you want to have a specific date it is always related to the time zone of the user. Then you can convert the timestamp into a user-formatted date. Like mentioned by Zaph he might want to see the date where he currently is. Again with the timestamp this is always reliable.
If you want to calculate that an entry can be done only once per calendar day in the location where somebody is, then you can calculate with ˙NSCalendar˙ and ˙NSDateComponents˙ for example what day a timestamp represents and then from the beginning of that day calculate 24 hours up. Conversion back to a timestamp gives you a helpful range for check if something is within the same calendar day. The NSCalendar is the base for calculation even if you will probably use Gregorian most of the time. With the NSDateComponentsyou can what ever part you want from your Timestamp (e. g. only the day, the month, the year, etc.).

Predicate on to-many relationship

I have a managed object reference *event.
An Event has many Occurrences. An Occurrence has an attribute call date
I want to fetch all the occurrences of the event *event which has today's date. How should I write a NSPredicate on a FetchRequest.
Here is the construction of the predicate to filter out the event which occurs today.
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components =[gregorian components:(NSDayCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit) fromDate:today];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSDate *todayMidnight=[gregorian dateFromComponents:components];
#define Hours_24 86400
NSDate *tomorrowMidnight=[NSDate dateWithTimeInterval:Hours_24 sinceDate:todayMidnight];
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"occurance.date >= %# AND occurance.date< %#",todayMidnight,tomorrowMidnight];
[gregorian release];
Since the attribute of occurance is of NSDate datatype, it will have the time as well as the date. So, this predicate will filter out all occurances whose date falls between today midnight and tomorrow midnight. Another way(and better, in my opinion), would be to get the Occurances and then do the filtering.
Don't forget to setPropertiesToFetch: to occurance if you want only the occurance and not the event. This will return an NSDictionary.
You have to be aware, that there are two ways to get your Occurrence objects: You can traverse the relationship from the Event object (i.e. myEvent.occurences) or you can create a fetch request for all occurrences that have the event of interest in their inverse relationship, i.e. a predicate like [NSPredicate predicateWithFormat:#"event == %#", myEvent"].
There are fundamental differences to these two. A fetch request will always cause SQL to be executed and I/O to happen which is expensive. If you simply traverse the relationship, and you're in a situation where the Occurrence objects are already in memory, it will be very cheap to do (no SQL, no I/O). The fetch request on the other hand, will allow you to fault in all objects in one go, while traversing will only fault objects one at a time, so you'll end up doing multiple SQL + I/O events. Also, a fetch request allows you to limit the predicate even further. But in many cases, simply traversing might be the best case.
CoreData does a lot of heavy lifting for you, but at the end of the day, you still need to know about when to do SQL and I/O and how to prevent it.
I hope this helps.

Resources