Skip to content

Instantly share code, notes, and snippets.

@jbenet
Created April 7, 2011 11:27
Show Gist options
  • Save jbenet/907603 to your computer and use it in GitHub Desktop.
Save jbenet/907603 to your computer and use it in GitHub Desktop.
Objective-C AskGeo API
// The MIT License
//
// Copyright (c) 2010 Juan Batiz-Benet
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// NSTimeZone (AskGeo)
// @author Juan Batiz-Benet
//
// This category helps to get local time for a particular location.
//
// WHY USE THIS:
// - While iPhones and Macs constantly update their times, iPods do not.
// - Game players exploit time-sensitive mechanics by changing time settings.
//
// DIRECTIONS:
// - Get an AskGeo API Key
// - Set your API Key inside NSTimeZone+AskGeo.m
// - Add NSTimeZone+AskGeo.{hm} to your project
//
// DEPENDENCIES:
// - CoreLocation (optional)
// - YAJL-objc (or an equivalent) https://github.com/gabriel/yajl-objc
#import <CoreLocation/CoreLocation.h>
@interface NSTimeZone (AskGeo)
// NOTE! These are blocking calls. I recommend that you call these from a
// background thread.
// to avoid linking against CoreLocation, comment the following two lines,
// the methods in .m, and just use the lat/lon one.
+ (NSTimeZone *) timeZoneForCoordinate:(CLLocationCoordinate2D)coordinate;
+ (NSTimeZone *) timeZoneForLocation:(CLLocation *)location;
+ (NSTimeZone *) timeZoneForLatitude:(float)lat andLongitude:(float)lon;
@end
// The MIT License
//
// Copyright (c) 2010 Juan Batiz-Benet
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// NSTimeZone (AskGeo)
// @author Juan Batiz-Benet
//
// This category helps to get local time for a particular location.
//
// WHY USE THIS:
// - While iPhones and Macs constantly update their times, iPods do not.
// - Game players exploit time-sensitive mechanics by changing time settings.
//
// DIRECTIONS:
// - Get an AskGeo API Key
// - Set your API Key inside NSTimeZone+AskGeo.m
// - Add NSTimeZone+AskGeo.{hm} to your project
#import "NSTimeZone+AskGeo.h"
#import <CoreLocation/CoreLocation.h>
#import <YAJL/YAJL.h>
// Change these constants to your account and API Key:
static const NSString *kASKGEO_ACCOUNT = <PUT YOUR ACCOUNT HERE>;
static const NSString *kASKGEO_API_KEY = <PUT YOUR API KEY HERE>;
static NSString *kASKGEO_API_URL =
@"http://www.askgeo.com/api/%@/%@/timezone.json?points=%f,%f";
@implementation NSTimeZone (AskGeo)
// to avoid linking against CoreLocation, comment the following two methods,
// and just use the lat/lon one at the bottom.
+ (NSTimeZone *) timeZoneForCoordinate:(CLLocationCoordinate2D)coord {
return [self timeZoneForLatitude:coord.latitude andLongitude:coord.longitude];
}
+ (NSTimeZone *) timeZoneForLocation:(CLLocation *)location {
return [self timeZoneForCoordinate:location.coordinate];
}
+ (NSTimeZone *) timeZoneForLatitude:(float)lat andLongitude:(float)lon {
// setup the URL:
NSString *urlString = [NSString stringWithFormat:kASKGEO_API_URL,
kASKGEO_ACCOUNT, kASKGEO_API_KEY, lat, lon];
NSURL *url = [NSURL URLWithString:urlString];
// Make the request
NSString *res = nil;
NSError *error = nil;
NSStringEncoding encoding = NSASCIIStringEncoding;
res = [NSString stringWithContentsOfURL:url encoding:encoding error:&error];
// Request error checking
if (res == nil || error != nil) {
NSLog(@"WARNING NSTimeZone+AskGeo: Error making request (url: %@)", url);
return nil;
}
// Parse response
NSDictionary *response = nil;
@try {
response = [res yajl_JSON];
} @catch (id exception) {
NSLog(@"%@", exception);
}
// Response error checking
if (response == nil || ![response isKindOfClass:[NSDictionary class]]) {
NSLog(@"NSTimeZone+AskGeo: Error parsing response. (%@)", response);
return nil;
}
NSNumber *code = [response valueForKey:@"code"];
if (code == nil || ![code isKindOfClass:[NSNumber class]]) {
NSLog(@"NSTimeZone+AskGeo: Error with format. Response has no code.");
return nil;
}
if ([code intValue] != 0) { // 0 = success.
NSString *msg = [response valueForKey:@"message"];
NSLog(@"NSTimeZone+AskGeo: AskGeo Error %d: %@", [code intValue], msg);
return nil;
}
NSArray *data = [response valueForKey:@"data"];
if (data == nil || ![data isKindOfClass:[NSArray class]]) {
NSLog(@"NSTimeZone+AskGeo: Error with format. Response has no data.");
return nil;
}
if ([data count] == 0) {
NSLog(@"NSTimeZone+AskGeo: Error with format. Empty data.");
return nil;
}
NSDictionary *result = [data objectAtIndex:0];
if (result == nil || ![result isKindOfClass:[NSDictionary class]]) {
NSLog(@"NSTimeZone+AskGeo: Error with format. Bad data.code[0].");
return nil;
}
NSString *tzStr = [result valueForKey:@"timeZone"];
if (tzStr == nil || ![tzStr isKindOfClass:[NSString class]]) {
NSLog(@"NSTimeZone+AskGeo: Error with format. Bad data.code[0].timeZone.");
return nil;
}
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:tzStr];
if (timeZone == nil) {
NSLog(@"NSTimeZone+AskGeo: NSTimeZone does not recognize name %@", tzStr);
}
return timeZone;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment