Since NSDate represents "a single point in time, independent of any particular calendrical system or time zone", is it OK to make direct calculations with seconds given by its methods like timeIntervalSince1970?
I mean operations like add and subtract of two NSTimeInterval (aka double) values rather than using dateByAddingTimeInterval: or NSCalendar method like - (nullable NSDate *)dateByAddingComponents:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSCalendarOptions)opts.
What issues would have such direct calculations?
Adding may make less sense, but subtracting does make sense if you want to find the difference in time between two dates.
What you want to note, however, is that you should only go for the seconds, minutes, hours, days, weeks difference from your subtraction
But to find the difference in months and years, you will want to use the NSDate API. Months and years are not constant
Likewise with adding dates, if you want to add seconds, minutes, hours, days, weeks. Those are constant and easy to add. But Months and Years will trip you up
Related
I'm working on a Core Data project, I have a table with a modification_date field,
I need to extract all the entries of the last n days that also have a modification_date between (let's say) 1PM and 9PM.
I've already sorted out part of the solution to extract just the entries in the last n days
like suggested in: Core Data- predicate with dates
NSDate *today = [NSDate date];
NSDate *end_day = [today addTimeInterval: (days*86400.0f)];
day_st = [NSString stringWithFormat: #"(timestamp >= %#) AND (timestamp <= %#) AND ", today, end_day];
My only problem now, would be adding the filter by time spans.
But, except for making a foreach to check the time of every single element in the result,
I can't come up with anything clever.
If you're storing date-type fields in your data model, there's no good way to do that. Those get stored as the number of seconds since a reference date-- so filtering on an NSDate works, since it's the same thing. You can't build a predicate based on date components (like hour of the day) though, because the data store doesn't know anything about those. Filtering the results after fetching them from the data store is a reasonable approach in most cases.
If this is something you'll do a lot, you might consider adding one or more new attributes-- for example, an integer field where you store the hour of the day. Then you could include those fields in your NSPredicate. Set the value for these fields any time the date field changes. And, be damn sure you know what time zone those fields are in. UTC is preferable. Local time is asking for trouble. With UTC you'd covert "1PM", "9PM", etc to their equivalents in UTC before setting values for the fields and before fetching.
Finally (and you may have realized this, but it's not obvious from your question), note that the other question you link to is building an NSPredicate while you have an NSString there.
I'd say you're looking to end up with a predicate like:
((timestamp >= <startTimeOnDayOne>) AND (timestamp <= <endTimeOnDayOne>)) OR
((timestamp >= <startTimeOnDayTwo>) AND (timestamp <= <endTimeOnDayTwo>)) OR
[...]
In terms of how you'd formulate the appropriate Cocoa date objects, you'd probably want to seed two NSDateComponents, one for the start time and one for the end time, and a third that simply says 'one day'. Then use an NSCalendar (just the current calendar if you're being that vague about it) and its dateFromComponents: and dateByAddingComponents:toDate:options: methods — the former to get the dates for the first day and then the latter to advance each by one day.
If you attempt just to add 24 hours at each juncture you'll get the wrong result twice a year in any territory with daylight savings.
You can build up the NSPredicates for each relevant day into an array and then use NSCompoundPredicate +orPredicateWithSubpredicates: to glue them all together into a single predicate at the end, allowing you to worry about how many is n days at runtime.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to calculate time in hours between two dates in iOS
I am beginner to Objective-C, so I need your help in syntax making.
My problem goes like this:
I have 2 Strings, and I want to convert that into NSDate and then calculate the time difference between the dates in minutes.
How can I do this?
Use NSDateFormatter to convert the date strings into NSDate objects.
Call -[NSDate timeIntervalSinceDate:] to get the difference between the two dates in seconds.
Divide by 60 to get the difference in minutes.
Alternatively, you can use NSCalendar and NSDateComponents to calculate the difference in minutes for different calendars by using the components:fromDate:toDate:options: method.
I need to get the current date, but ignoring minutes and seconds, and then calculate an interval.
For example say that it's 7:30am right now, and I need to see how many hours it is until 5pm the next day, not counting the minutes, which means 7:30am should equal to 7am in this scenario, and the result should be 22 hours.
This could be easily done with
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
assuming that I'm able to create both ends of the interval.
The only option I thought of is using NSDateFormatter to output the current date into a string without the minutes, and then parse it back. But that doesn't seem like a very elegant and efficient solution.
What I basically need to do is trim a NSDate to a specific precision, such as days, and trim the rest (7:50 to 7:00, etc.).
Or is there any simple way I can do this the smarter way, where 7:50 gets roudned to 8:00 instead of 7:00?
I need to do this on iOS 5.
The calculations can be done with NSCalendar, instead of parsing you can use NSDateComponents.
When you take the hours and minutes from NSDateComponents, you can easily apply your rounding and convert the components back to a date.
I'm currently creating a scheduling application that deals with schools schedules. Each schedule has an array of period objects that contains both a start and an end time. Currently I have these times stored as NSDate objects, where only the time is really relevant and each NSDate object has some arbitrary date associated with it that is largely insignificant to my application (it's whatever the UIDatePicker assigns to it, but I only use the TimePickerMode). I do a number of things with these dates. First, I use an NSDateFormatter to output a string representation of the time for each period in a UITableView. I then also attempt to find the current period in the day by comparing the current time, fetched by [NSDate date], to the start and end time. But I am having trouble deciding the best way to do this.
Currently, I use an NSDateFormatter to convert the start and end times to strings, and then back to dates that now have a date the same as today's date. Then after that I can do my date comparisons using - (NSComparisonResult)compare: comparing the start and end dates to the current date. However, I could see this as being very inefficient.
Other possible ways could be to convert each NSDate to NSDateComponents, then use NSCalendar to convert that back into an NSDate with the current date and the same original time.
Or, I could take a different approach and ditch the NSDate storage technique altogether. Instead I could store each start and end time as NSDateComponents, then it would be simple enough to output a formatted version of the time for the UITableView, and then I could convert the date obtained by [NSDate date] to NSDateComponents to be used for logical comparisons to obtain the current period.
I see three or four different ways of going about this, and actually after talking it out I I'm pretty confident the final way I discussed would be the most efficient as it requires the least amount of runtime conversions between different types of date objects. I'm just looking for other people's inputs.
The problem with using NSDate to store a time-of-day is that its value is dependent on the time zone. If the time zone or DST changes while your app is running in the foreground or background, then all of your times will suddenly be wrong. Ditto if you actually save NSDate values to disk. (One option is to set your app's default time zone to UTC, but then your app's idea of "now" will be incorrect to the user).
I would store the time separately and implement methods to convert to and from NSDate. You could store the time using NSDateComponents, or you could just store it as a single integer (say, minutes past midnight) which makes it trivial to compare two times.
When converting minutes to and from NSDate you use NSDateComponents, and you need to make sure that your UIDatePickers, NSCalendars, and NSDateFormatters are using the same time zone, which by default is the local time zone.
It seems like you're worried about the overhead that NSDateFormatter currently levies on your program to synchronize the day of your periods and the current date. But really, you don't care about the date at all, you just want the time since the beginning of the day.
Why not cut out the middleman? Store the start and end times as NSTimeIntervals, which are really just doubles. Mod the start and end times by 86,400, the seconds in a day, in order to distill the time down to simply the time in seconds after the start of a new day. You don't really care what day it represents, except that that day is represented as second 0.
Then whenever you pull the current NSDate, mod its NSTimeInterval by 86,400 to obtain the time in seconds and compare it against the stored period values. The only object conversion involved in the whole process would be using the primitive timeIntervalSinceReferenceDate. The rest are simple mod and comparison operators, and you get to store your period numbers as simple NSTimeIntervals.
I'm putting together an application that will require the recording of dates as far back as the BC range; can Core Data's date type handle this, or do I need to define another entity to properly record and format dates?
NSDate works using NSTimeInterval which is a double.
always specified in seconds; it yields sub-millisecond precision over a range of 10,000 years.
I'm not going to work out how far back in time a double will go (order of +/- 10^300 seconds or so), but I think you will be safe to use it for the BC ranges. For example: 1,000 years is about 3x10^11 seconds.
Perhaps this is useful, NSDate distantPast gives you:
0001-12-31 19:43:12 -041648
and NSDate distantFuture gives you:
4000-12-31 21:00:00 -0300