Created
September 8, 2013 05:45
-
-
Save AnuragMishra/6482177 to your computer and use it in GitHub Desktop.
Date parsing performance comparison
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 <Foundation/Foundation.h> | |
#include <time.h> | |
#include <xlocale.h> | |
#import "sqlite3.h" | |
#import "ISO8601DateFormatter.h" | |
#define LOG_DATE 0 | |
static NSUInteger count = 1000000; | |
typedef int64_t timestamp; | |
NSUInteger randomNumberInRange(NSUInteger start, NSUInteger end); | |
// Create a sample date using the ISO-8601 format. | |
// 2013-04-23T16:29:05Z | |
NSString* generateSampleDate(); | |
// Create an array of <count> dates in the ISO-8601 format. | |
NSArray *generateSampleDates(NSUInteger count); | |
// Parse all given dates using SQLite's strftime function | |
void parseDatesUsingSQLite(NSArray *dates); | |
// Parse all given dates using NSDateFormatter | |
void parseDatesUsingNSDateFormatter(NSArray *dates); | |
// Use SQLite implementation directly | |
void parseDatesUsingSQLiteImpl(NSArray *dates); | |
// Use the library IS08601 written by Peter Hosey | |
void parseDatesUsingISO8601Parser(NSArray *dates); | |
// Use strptime and gmtime from time.h | |
void parseDatesUsingGMTime(NSArray *dates); | |
timestamp unixDate(int year, int month, int day, int hour, int minute, int second); | |
static NSDateFormatter *dateFormatter = nil; | |
static ISO8601DateFormatter *isoDateFormatter = nil; | |
int main() | |
{ | |
@autoreleasepool | |
{ | |
printf("Generating sample data with %lu dates\n", count); | |
NSArray *dates = generateSampleDates(count); | |
printf("Sample data generation complete. Commencing tests...\n\n"); | |
NSDate *start = nil; | |
NSDate *end = nil; | |
start = [NSDate date]; | |
parseDatesUsingSQLite(dates); | |
end = [NSDate date]; | |
printf("sqlite3 took %4.3f seconds\n", [end timeIntervalSinceDate:start]); | |
start = [NSDate date]; | |
parseDatesUsingNSDateFormatter(dates); | |
end = [NSDate date]; | |
printf("NSDateFormatter took %4.3f seconds\n", [end timeIntervalSinceDate:start]); | |
start = [NSDate date]; | |
parseDatesUsingSQLiteImpl(dates); | |
end = [NSDate date]; | |
printf("SQLite's implementation in C took %4.3f seconds\n", [end timeIntervalSinceDate:start]); | |
start = [NSDate date]; | |
parseDatesUsingISO8601Parser(dates); | |
end = [NSDate date]; | |
printf("ISO8601DateFormatter took %4.3f seconds\n", [end timeIntervalSinceDate:start]); | |
start = [NSDate date]; | |
parseDatesUsingGMTime(dates); | |
end = [NSDate date]; | |
printf("strptime/gmtime took %4.3f seconds\n", [end timeIntervalSinceDate:start]); | |
} | |
return 0; | |
} | |
NSArray *generateSampleDates(NSUInteger count) | |
{ | |
NSMutableArray *dates = [NSMutableArray array]; | |
for (int i = 0; i < count; i++) | |
{ | |
[dates addObject:generateSampleDate()]; | |
} | |
return dates; | |
} | |
NSString* generateSampleDate() | |
{ | |
NSUInteger year = randomNumberInRange(1980, 2013); | |
NSUInteger month = randomNumberInRange(1, 12); | |
NSUInteger date = randomNumberInRange(1, 28); | |
NSUInteger hour = randomNumberInRange(0, 23); | |
NSUInteger minute = randomNumberInRange(0, 59); | |
NSUInteger second = randomNumberInRange(0, 59); | |
NSString *dateString = [NSString stringWithFormat:@"%lu-%02lu-%02luT%02lu:%02lu:%02luZ", | |
year, | |
month, | |
date, | |
hour, | |
minute, | |
second | |
]; | |
return dateString; | |
} | |
void parseDatesUsingSQLiteImpl(NSArray *dates) | |
{ | |
static const char *scanFormat = "%d-%d-%dT%d:%d:%d"; | |
int year, month, date, hour, minute, second; | |
for (NSString *dateString in dates) | |
{ | |
sscanf(dateString.UTF8String, scanFormat, &year, &month, &date, &hour, &minute, &second); | |
timestamp interval = unixDate(year, month, date, hour, minute, second); | |
NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval]; | |
#if LOG_DATE | |
NSLog(@"%@", date); | |
#endif | |
} | |
} | |
void parseDatesUsingSQLite(NSArray *dates) | |
{ | |
sqlite3 *db = NULL; | |
sqlite3_open(":memory:", &db); | |
sqlite3_stmt *statement = NULL; | |
sqlite3_prepare_v2(db, "SELECT strftime('%s', ?);", -1, &statement, NULL); | |
for (NSString *dateString in dates) | |
{ | |
sqlite3_bind_text(statement, 1, [dateString UTF8String], -1, SQLITE_STATIC); | |
sqlite3_step(statement); | |
timestamp value = sqlite3_column_int64(statement, 0); | |
NSDate *date = [NSDate dateWithTimeIntervalSince1970:value]; | |
#if LOG_DATE | |
NSLog(@"%@", date); | |
#endif | |
sqlite3_clear_bindings(statement); | |
sqlite3_reset(statement); | |
} | |
} | |
void parseDatesUsingNSDateFormatter(NSArray *dates) | |
{ | |
if (dateFormatter == nil) | |
{ | |
dateFormatter = [[NSDateFormatter alloc] init]; | |
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; | |
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; | |
} | |
for (NSString *dateString in dates) | |
{ | |
NSDate *date = [dateFormatter dateFromString:dateString]; | |
#if LOG_DATE | |
NSLog(@"%@", date); | |
#endif | |
} | |
} | |
NSUInteger randomNumberInRange(NSUInteger start, NSUInteger end) | |
{ | |
NSUInteger span = end - start; | |
return start + arc4random_uniform(span); | |
} | |
timestamp unixDate(int year, int month, int day, int hour, int minute, int second) | |
{ | |
int century, b, x1, x2; | |
int64_t julianDay; | |
if (month <= 2) | |
{ | |
year--; | |
month += 12; | |
} | |
century = year / 100; | |
b = 2 - century + (century / 4); | |
x1 = 36525 * (year + 4716) / 100; | |
x2 = 306001 * (month + 1) / 10000; | |
julianDay = (int64_t)((x1 + x2 + day + b - 1524.5 ) * 86400000); | |
julianDay += (hour * 3600000) + (minute * 60000) + (int64_t)(second * 1000); | |
int64_t unixTime = (julianDay / 1000) - (21086676 * (int64_t)10000); | |
return unixTime; | |
} | |
void parseDatesUsingISO8601Parser(NSArray *dates) | |
{ | |
[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:+0]]; | |
if (isoDateFormatter == nil) | |
{ | |
isoDateFormatter = [[ISO8601DateFormatter alloc] init]; | |
isoDateFormatter.parsesStrictly = YES; | |
} | |
for (NSString *dateString in dates) | |
{ | |
NSDate *date = [isoDateFormatter dateFromString:dateString]; | |
#if LOG_DATE | |
NSLog(@"%@", date); | |
#endif | |
} | |
} | |
void parseDatesUsingGMTime(NSArray *dates) | |
{ | |
struct tm sometime; | |
const char *formatString = "%Y-%m-%dT%H:%M:%SZ"; | |
for (NSString *date in dates) | |
{ | |
strptime_l([date UTF8String], formatString, &sometime, NULL); | |
NSDate *date = [NSDate dateWithTimeIntervalSince1970: timegm(&sometime)]; | |
#if LOG_DATE | |
NSLog(@"%@", date); | |
#endif | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment