Created
March 14, 2010 09:59
-
-
Save henrik/331897 to your computer and use it in GitHub Desktop.
AKServerTime (Obj-C/Cocoa). Keeps track of server time, adjusting for time zone/time sync diffs and accounting for latency.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// AKServerTime | |
// By Henrik Nyh <http://henrik.nyh.se> 2010-03-14 under the MIT license. | |
// | |
// Keeps track of the current server time, adjusting for differences in | |
// time zone/time sync between client and server, and accounting for latency. | |
// | |
// The latency adjustment is pessimistic: if we get 12:00:25 back with a latency | |
// of 5 seconds, we know the current server time is between 12:00:25 (5 sec req, | |
// 0 sec res) and 12:00:30 (0 sec req, 5 sec res). We assume it is 12:00:30 so | |
// that trusting the server time may make you early, but never late. | |
// | |
// This is a singleton class: get it with [AKServerTime sharedServerTime]. | |
#import <Foundation/Foundation.h> | |
@interface AKServerTime : NSObject { | |
NSTimeInterval _offset; | |
NSTimeInterval _latency; | |
} | |
+ (id)sharedServerTime; | |
- (void)syncWithClientDate:(NSDate *)clientDate serverDate:(NSDate *)serverDate andLatency:(NSTimeInterval)latency; | |
- (NSDate *)date; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "AKServerTime.h" | |
static AKServerTime *sharedServerTime = nil; | |
@implementation AKServerTime | |
#pragma mark - | |
#pragma mark Date | |
- (void)syncWithClientDate:(NSDate *)clientDate serverDate:(NSDate *)serverDate andLatency:(NSTimeInterval)latency { | |
NSDate *pessimisticServerDate = [serverDate addTimeInterval:latency]; | |
NSTimeInterval offset = [pessimisticServerDate timeIntervalSinceDate:clientDate]; | |
// If we've synced with smaller latency before, and the offset is not | |
// large enough (under 5 seconds) to suspect something like a DST change, | |
// keep the old value as more reliable. | |
if (_latency && _latency < latency && (fabs(offset-latency) < 5.0)) { | |
NSLog(@"SERVER TIME: higher latency at %f, remaining offset small at %f - keep old value", latency, fabs(offset-latency)); | |
} else { | |
_latency = latency; | |
_offset = offset; | |
} | |
NSLog(@"SERVER TIME: local now %@ server now %@ (latency %f, offset %f)", | |
[NSDate date], [self date], _latency, _offset); | |
} | |
- (NSDate *)date { | |
return [[NSDate date] addTimeInterval:_offset]; | |
} | |
#pragma mark - | |
#pragma mark Singleton | |
// http://iphone.galloway.me.uk/iphone-sdktutorials/singleton-classes/ | |
+ (id)sharedServerTime { | |
@synchronized(self) { | |
if(sharedServerTime == nil) | |
[[self alloc] init]; | |
} | |
return sharedServerTime; | |
} | |
+ (id)allocWithZone:(NSZone *)zone { | |
@synchronized(self) { | |
if(sharedServerTime == nil) { | |
sharedServerTime = [super allocWithZone:zone]; | |
return sharedServerTime; | |
} | |
} | |
return nil; | |
} | |
- (id)copyWithZone:(NSZone *)zone { | |
return self; | |
} | |
- (id)retain { | |
return self; | |
} | |
- (unsigned)retainCount { | |
return UINT_MAX; //denotes an object that cannot be released | |
} | |
- (void)release { | |
// never release | |
} | |
- (id)autorelease { | |
return self; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment