Different result for [NSDate date] in several devices
Asked Answered
F

4

5

To start, I have to say that I set autoset in date&time settings and time zone is the same for each device. So I use [NSDate date] to get time stamp in milliseconds, then encode to NSData and send to another device. On receiver data is being decoded and subtract with new [NSDate date]. So that I get total time needed for send and receive message. That I was thought because when sender is iPhone 4 iOS6 and receiver is iPhone 5 iOS7 then receiver have earlier time stamp than sender. I don't know why? Maybe [NSData date] isn't the most reliable class for that kind of operations? I use GCDAsyncUdpSocket for sending/receiving UDP.

Code sender

NSData *data2 = [self createRandomNSData:8192];
NSMutableData *dataToSend =[NSMutableData data];
[dataToSend appendBytes:&tag length:sizeof(int)];
long long currentTimeStamp = (long long)([[NSDate date] timeIntervalSince1970]*1000.0);
[dataToSend appendBytes:&currentTimeStamp length:sizeof(long long)];
[dataToSend appendData:data2];
NSLog(@"%i || %lld || %lu",tag, currentTimeStamp,(unsigned long)[dataToSend length]);
[_udpSocket sendData:dataToSend toHost:@"230.0.0.1" port:_port withTimeout:-1 tag:tag];
tag++;

Code receiver

char* dataBytes = [data bytes];
int inTag;
long long inCurrentTimeStamp;
[data getBytes:&inTag length:sizeof(int)];
[data getBytes:&inCurrentTimeStamp range:NSMakeRange(sizeof(int), sizeof(long long))];
long long currentTimeStamp = (long long)([[NSDate date] timeIntervalSince1970]*1000.0);
long long timeStampDiff = currentTimeStamp - inCurrentTimeStamp;
self.delay = timeStampDiff;
NSLog(@"%i || %lld || %lu",inTag, timeStampDiff,(unsigned long)[data length]);
Feu answered 6/12, 2013 at 14:7 Comment(5)
You should at least show the output of the NSLog calls.Paleolithic
Yeah, how much of a difference are you talking about here? You NSLog it, but you don't give the results.Sickler
what about the timezones? are they the same?Subnormal
@Subnormal yes timezones are the same.Digital
Why don't you send a message from 'client' to 'server' and then back from your 'server' to the 'client' device to get the total ping time. To get the value you are currently trying to calculate, you can simply divide the value by two.Shedd
H
5
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yyyy hh:mm:ss"];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
NSString *strSystemTime = [dateFormatter stringFromDate:[NSDate date]];

I faced the same issue and resolved it by setting NSLocale. I hope this solution works for you too.

Hokku answered 18/12, 2013 at 5:46 Comment(0)
A
2

Don't use a long long of the NSDate's timeIntervalSince1970 * 1000. Use the timeIntervalSince1970 expressed as a double, directly. That will save all the resolution of the date.

Simply add bytes to your data that are the sizeof(double).

Log the double value and it's byte stream before sending, and the double value and it's byte stream on receipt on the remote device and compare them.

If both devices are phones on the same network, and you have them to set their clocks automatically (settings>general>date and time) then their clocks should be synchronized within a fraction of a second.

Amir answered 6/12, 2013 at 14:19 Comment(2)
Didn't [[NSDate date] timeIntervalSince1970] without multiply by 1000 return only seconds and I need milliseconds.Digital
@Duidi, [[NSDate date] timeIntervalSince1970] returns fractional seconds since 1970. I would suggest saving it in that format to preserve all the information, and then multiplying it by 1000 when you need to calculate milliseconds.Amir
W
1

On receiver data is being decoded and subtract with new [NSDate date]

That's the problem. It has nothing to do with the iOS version installed on the device: in general, if your timestamps are produced by different computers, you cannot subtract them, and expect any kind of precision to come out of it, because the device clocks are not synchronized enough to measure network latency, because of clock skew.

Consider this simplistic example: let's say the clocks on computers Alice and Bob are 10 seconds apart: when Alice's clock shows 12:00:00, Bob's clock shows 12:00:10.

Alice sends Bob its timestamp, which says 14:23:06. It takes the package one second to reach Bob, now Bob sees 14:23:17 when the package arrives. If Bob simply subtracts Alice's timestamp from his own, he would conclude that the package took 11 seconds to reach it.

If Bob sends Alice his timestamp now - let's say it's 14:23:18, Alice would receive it one second later, which by Alice's clock would be 14:23:09. Now Alice would conclude that the package took -9 (yes, negative nine!) seconds to reach it, which makes no sense at all.

Fortunately, if it is fair to assume that the latency is the same on both legs of the round-trip, you can measure the latency by factoring out the clock skew. The idea is to obtain two pairs of timestamps constructed in such a way that the clock skew is a factor in both pairs, but the sign of the skew is opposite.

Consider the timestamps from the above example:

A1=14:23:06 B1=14:23:17
B2=14:23:18 A2=14:23:09

Each pair, A1-B1 and B2-A2, contain the skew, but in the first pair the skew is positive, while in the second pair it is negative. Hence, if you average the two time differences, you would end up with your roundtrip delay.

((B1-A1)+(A2-B2)) / 2 =
(11 + -9) / 2         =
2 / 2                 = 1 second

This should be enough for you to implement a simple program for measuring the roundtrip latency in your system.

Warmth answered 17/12, 2013 at 22:4 Comment(3)
[off topic] Lol... I think I have the exact same hats as you on SO :PClypeus
@DoorknobofSnow I think you've got at least one that's different - the secret one you're wearing right now. How did you get it, if you don't mind me asking?Warmth
I actually got that one on meta. It's for getting the Necromancer badge. :)Clypeus
A
0
long  intervalValue= (long)([[NSDate date]  timeIntervalSince1970]);

NSString *intervalString =[NSString stringWithFormat:@"%ld",intervalValue];

int dif=13-[intervalString length];

for (int k=0; k<dif; k++) {

    intervalString=[NSString stringWithFormat:@"%@0",intervalString];
}

unsigned long long convertedValue=[intervalString longLongValue]+0530;
Anabatic answered 17/12, 2013 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.