Precise measurement of time interval in CocoaTouch - objective-c

I have a class which must have a property of some kind of timestamp, representing the moment of time when the instance of this class was created. And then when having multiple objects of this class I need to find the time interval between the creation of these objects.
And the usual interval is going to be up to 10 seconds, so I need precision of at least 1 second, but something like 0.1-0.001 second would be much better.
What is the best option to use for this property?
As far as I know, NSDate has precision up to 1 second.
I believe that I need something related to CFTimeInterval. I've used it for view animation with CADisplayLink. It provided the CFTimeInterval value for each moment of screen update and I could calculate the time interval between two CFTimeInterval's very easily.
But how do I assign the value to this CFTimeInterval at any moment of time?

NSDate will work, as Matthias Bauch's comment indicates. You can also just use CFTimeIntervals though:
CFTimeInterval currentTime = CFAbsoluteTimeGetCurrent();
Do note that this function and NSDate are both based on an absolute reference date (Jan 1, 2000 in this case). This means that if the system's clock is changed while your app is running, values obtained before the clock change won't correctly compare to values obtained afterward.

Related

SKScene's update method gets a "currentTime" that is different from CFAbsoluteTimeGetCurrent()

The problem can be reproduced in an freshly created SpriteKit project.
After creating a new project, I add two lines to the update: method of the MyScene class:
-(void)update:(CFTimeInterval)currentTime {
NSLog(#" currentTime = %f", currentTime);
NSLog(#"CFAbsoluteTimeGetCurrent() = %f", CFAbsoluteTimeGetCurrent());
}
Running this shows that currentTime is several orders of magnitude smaller than the time returned by CFAbsoluteTimeGetCurrent(). I searched for possible reasons, but found none. The only possibility I could think of is that currentTime is the time frame since some other date than 00:00:00 01.01.2000, but I have no idea what other reference point it would be using, and found nothing when searching online either.
What can I do to get the current time, calculated by the same rules that are used to calculate currentTime?
Nothing, unless you're willing to disassemble and understand the Sprite Kit framework code.
Though the problem is most likely explained by Sprite Kit taking CFAbsoluteTimeGetCurrent at an earlier point in time, which is then passed into the update: method. Simply the overhead of sending that message to the scene means that the two times can't be the same. Or the currentTime may not be obtained by CFAbsoluteTimeGetCurrent but some other means.
What you can do is to get the currentTime of the very first time update: runs and store it in an ivar. You can then use this time as the reference time for the scene.
currentTime is a CFTimeInterval, so I expect it is the interval between some point in time and the current time - probably the interval since a scene was started. If you let your scene running for a minute, do the values get close to 60.0 (60 seconds)?
CFAbsoluteTimeGetCurrent is a CFAbsoluteTime, that is the number of seconds since Jan 1st 2001, so that should always be around 500 million or so.

How To Get Time Since Like 1972 in Objective-C

I know in python that you can get the time in milliseconds since 1972 or some time around there. I wanted to know if there was a similar feature in Objective-C or if I need to make something to calculate it.
Well, there's [[NSDate date] timeIntervalSince1970], which give the time (in seconds) since midnight on January 1, 1970.
[NSDate date] returns the current time; you can get the seconds-since-epoch relative to any time that you have an NSDate object for.
From the sound of it, you don’t care about the particular start date, just an elapsed-time number you can get milliseconds from. CFAbsoluteTimeGetCurrent() will give you a double-precision value for the current system time.
If it doesn't have to be Objective-C:
long timeSinceEpoch = time(NULL);

timeIntervalSinceDate in past?

I'm creating a NSDate in the past (1 hour in the past) and that looks to be setting correct, only thing is I want to then use that to determine if an even has happened or not. Because I set to be in the past, when I do the check it should definitely think the even has happened, but timeIntervalSinceDate seems to only give a positive result?
This is the code I'm using with timeIntervalSinceDate
NSDate *now = [NSDate date];
NSTimeInterval secondsSincePlantingInterval = [now timeIntervalSinceDate:plantingDate];
Which is giving 68 seconds, but it should be -68 seconds, or does it not return negative values?
This is perfectly normal, documented behavior
The documentation states :
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
Return Value
The interval between the receiver and anotherDate. If the receiver is earlier than anotherDate, the return value is negative.
Since plantingDate is in the past, the receiver is not earlier than it. Therefore the value is positive.
Moreover ; this is plain english
[now timeIntervalSinceDate:plantingDate];
So, the time interval since the plantingDate up to now is positive.
It does return negative values, yes. But if plantingDate is in the past then I'd expect secondsSincePlantingInterval to be positive.
If you think about it, that line is reading:
Tell me the number of seconds now is since plantingDate.
Just like Tuesday 2nd is one day since Monday 1st, now is +ve seconds since plantingDate.
You want:
NSTimeInterval secondsSincePlantingInterval = [plantingDate timeIntervalSinceNow];

Working with time intervals in data logging?

I'm programming a data logging application. I need to be able to store a time interval typed in by the user using Core Data. For instance, if the user completes a task in seven minutes and twenty-three seconds, he/she can type 7:28 into the NSTextField and that will be part of the data.
What class should I use to store the time? NSDate seems to be the right way of doing it, but it does not seem to store time intervals. I see that there is an NSTimeInterval class. However, with no particular reference for it, I do not know how to use it.
Also, when this time interval is stored in objects within Core Data, I need to be able to retrieve those items and sort them (using NSSortDescriptor); in order to retrieve the entry that logged the lowest time interval. This is just additional information to help figure out what I need to do here.
From the docs: NSDate objects represent a single point in time.
From your use case it sounds like you want the user to log a relative time, and then to be able to sort by which is the smallest. In that case, NSDate is not a good option. The best solution is to just store the time interval as an NSUInteger, where the integer represents your value in seconds, and then do the appropriate conversions on either end.
If the user types in 7:28, could you convert this into seconds (448 seconds) and store it in a NSUInteger? That would make sorting it easily because you would not have to deal with separate minute and second values.
Here's what I think you should do:
Have two fields for user input: one for minutes and one for seconds.
Have some code like this:
NSInteger totalTime1 = 0;
totalTime += [minuteField.text integerValue]*60;
totalTime += [secondField.text integerValue];
Now store totalTime1 using Core Data. To retrieve the times and sort them, do something like this:
//Retrive times
NSArray *retrievedTimes = [NSArray arrayWithObjects: time1FromCoreDataAsNSNumber, time2FromCoreDataAsNSNumber, etc, nil];
NSArray *sortedRetrievedTimes = [retrievedTimes sortedArrayUsingSelector:#selector(compare:)];
//Now the array is sorted from lowest to highest
NSInteger lowestValue = [[sortedRetrievedTimes objectAtIndex:0] integerValue];
Hope this helps!

Is there a way to get timeIntervalSince1970 without using NSDate?

I'm trying to avoid creating an NSDate object since my code is heavy in needing the 'current time'. I end up calling [[NSDate date] timeIntervalSince1970] a lot. Is there any way to get the time interval without instantiating the object?
CFAbsoluteTimeGetCurrent gives you similar accuracy - no object required.
CFAbsoluteTimeGetCurrent uses a different base (or reference date), so you will have to initially determine the offset or the bases if you need to use another reference date (e.g. relative to some time in 1970).
NSTimeInterval interval = [NSDate timeIntervalSinceReferenceDate];
you deleted your comment regarding an option with more accuracy than CFAbsoluteTimeGetCurrent: try gettimeofday