Simultaneous NSDate generation leading to different time intervals - ios

In a server-client game using bluetooth connectivity (GameKit, specifically, for iOS6 compatibility), 1 or more client devices (iPhone/iTouch) send a timestamp to the server device (iPad) when a button on each client is tapped. i.e. each of the clients calls:
[[NSDate date] timeIntervalSince1970]
...and then sends to the server the value as an NSData payload.
When only 1 client is connected, the time being generated and sent to the server is the same as the time of the physical tap. When 2 or more clients are connected, the generated times differ significantly, even if all the clients are tapped at exactly the same time, e.g.
Client 1 and 2 simultaneously tapped:
client 1 timestamp = 1396974546.558433 (time interval since 1970)
client 2 timestamp = 1396974551.274747 (time interval since 1970)
i.e. client 2 is somehow 5 seconds out from client 1. While I'd accept a few milliseconds of difference since truly simultaneous tapping is hard, multiple seconds is unacceptable. Adding additional clients generates a more or less random difference in times, but usually several seconds.
To make things even more mysterious, the timestamps are being generated differently on the client: the timestamps being received at the server are the same as those being generated by the client (i.e. it's not something happening in transit or on receipt).
I'm at a loss for what's causing this. Any ideas?

[[NSDate date] timeIntervalSince1970] is relative to the time that's set on the device, so you can't rely on two devices sending the same time to your server.
I had a similar issue when developing something using Multipeer Connectivity, and ended up using a library called ios-ntp which uses time information from multiple NTP servers along with the latency of the request itself to derive the accurate time. It's worked pretty well for me.

My guess would be the devices are, for whatever reason, off by 5 seconds apart
my reason for saying this is that the
[[NSDate date] timeIntervalSince1970]
usually has sub millisecond accuracy

Related

Why TFS ServiceHooks delayed?

Why TFS ServiceHooks delayed in a few hours before it works.
In the history of the ServiceHooks it shows at Summary, sent at 11:13 while the response was at 09:13
Please check the web hooks sent time from history (reference below screenshot),
Take a look at the time setting(eg: China Standard time here) to check it’s the real delay but not due to Time zone difference.
If the delay happens consistently and each time delay hours, highly doubt it's a time zone difference, not a real delay. Please double check your server time zone and web site's.

iOS Time change notification and previous time

I have an application that works with timeout (let's say -> ring in 3 days). My problem occurs if a user change the device local time while being offline because I am comparing two NSDate (the final date and today) to check that timeout.
So I am trying to get notified when a user made a significant time change (several hours or days) in order to update my timers depending on the difference between before and after the update.
I found the UIApplicationSignificantTimeChangeNotification, which does :
Posted when there is a significant change in time, for example, change to a new day (midnight), carrier time update, and change to or from daylight savings time.
That nearly fits but I can't figure out how to get the "old" time in order to get the difference. I can't rely on a webserver neither because the app should be running in offline mode.
Any idea or suggest is welcome ;)
I finally find a way to solve my problem by using the CPU time (which is always constantly increasing except on reboot).
First time the app is launched, I get the Real time and the CPU time.
Then, when I need to check if time has been changed, I just take
the Real time at first, I add to it ( the current CPU time - the CPU time at first).
This give me the correct time.
Note: take care to use the real CPU time, not the one used by timer because it's stop when device go to sleep.
You should store the current time of your device, when your application goes into background. When the application comes into foreground, you should take the current time of your device. Now measure the difference between these 2 dates. If it is less than zero, it means, the user has set the device with previous date and you should throw the error of time out. If the difference is greater than 0, then you should compare current time with actual finish date.
One more indirect way is to start the location tracking of your device. Keep it on even when the app goes into background. When your didUpdateLocation delegate will hit by system, you will receive CLLocation object in argument. This location object is having currentTime details. Compare the time of last location and current location. If it is negative, user has bluffed with time. Its time to take the action.

Getting updated server time every second

I have a requirement where I need to know what is the server time at a given point of time in the app. As soon as the app connects to server, the server sends back the time and I am not sure how to update this time.
I thought of using the timers where the method is called every second and and a second is added to server time, so that whenever I ask for server time it is always updated one. But problem with this if we schedule this on main runloop, the run loop may or may not process the timer request if there it is busy.
So how to track the server time?
Thanks
Your server is in a specific time zone correct? Just get the time zone of the server using a request and show the time in that time zone in your app. You can then use a timer to continue updating the time every second.
I suggest getting just the time zone because if you get the server's time, there would be a lag between when the server sends back the response and when you get it - which defeats the whole purpose of getting the time as on the server.
You can't update the iOS system time from your app; there is no API
for that.
iPhone's time is usually very accurate. On iPads, it varies but has improved with iOS 5 to +/- 5 seconds if some form of internet connectivity is available.
If you want to manually connect to a server to synchronize time, you
should do it in a background task.
To compensate for latency, you should make multiple requests and add
the average half of the roundtrip time to the time sent by the server.
However, the question remains: Why do you want to do that anyway?

Store a value for "total number of time spent" in iPhone app

I am developing an iPhone application which stores the total time spent at a certain activity. I let the user press a button to start the activity and then stop. How can I store a value that keeps adding the time spent on the activity overall in the form of hours, minutes and seconds? (in Core Data or otherwise). For example: it can be shown like
Total time spent in a week: 08:12:05
could mean that the user spent 8 hours, 12 minutes and 5 seconds on the particular activity.
NSDate is unable to do it. I looked at NSTimer but that is kind of the opposite of what I'm looking for. I'm not thorough with all the api for iOS but is there something I can work with?
I would simply store NSDates for start and stop time, every time the user starts the activity. The time spent can be derived from these dates with -timeIntervalSinceDate:.
I mostly agree with Scott. If it was me I'd create a separate entity to hold activity times, each with a start and end time and whatever other data I need for that activity.
If you really prefer to store an accumulated time value, just store the number of seconds as one of the numeric types. Converting between that and the number of hours, minutes, and seconds is simple.

Is there a way to determine the actual time and date in iOS (not the time of the device)

In iOS, I need to know the actual time (UTC), not the time of the device. In other words, it should not be possible for the user to tamper with the time or date.
Anything that requires a network connection is not good (so accessing a time server is not an option).
AFAIK, there are 2 theoretical ways of achieving this:
Use the timestamp from the GPS satellite signal
Get the current time from the carrier
Problem is that this information is not exposed by any API in iOS.
Is there another way?
Most solutions you could possibly find (including getting GPS data from CoreLocation to access the time information) are flawed because they are depending on the actual device to access time time. You will need to connect to a time server (i would suggest to check for NTP server). I was looking at the core telephony framework and couldn't find anything that would provide the network time. You might want to fill a bug report and request apple to expand one of the classes to include the time.
You could have a look at secondsFromGMTForDate: and secondsFromGMT in NSTimeZone. If the GMT offset increases/decreases when the time of the device is changed, these provide a way to correct your timestamps to GMT (and probably convert to UTC).
You can't get to the raw GPS data and the timestamp property of the CLLocation in locationManager:didUpdateLocations: is set with the system clock

Resources