Cocoa中NSString到NSDate的处理(转载)

NSDate是NS类库中基础类型之一。随着数字化发展,程序对数据处理量越来越大,我们经常从服务器取得的日期是字符串序列,格式化为正确的date类型是一个不可避免的工作。在Cocoa程序里提供了非常方便的函数和类,但是仍然需要我们了解一些技巧。尤其是当我们的程序面对大量的日期字符串转换的时候,要格外的注意。苹果文档中使用NSDateFormatter类格式化日期字符串,但是以防读者不知道,我这里提一下:它的速度非常慢!!这篇文章介绍如何处理这种情况。

 
- (NSDate *)dateFromString:(NSString *)string {
//Wed Mar 14 16:40:08 +0800 2012
if (!string) return nil;
NSDateFormatter *dateformatter=dateformatter = [[NSDateFormatter alloc] init];
NSTimeZone *tz = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
[dateformatter setTimeZone:tz];
[dateformatter setDateFormat:@"EEE MMM dd HH:mm:ss Z yyyy"];;
return [dateformatter dateFromString:string];
}


由于NSDateFormatter内部代码原因,所以格式化字符串代价很大。对于个别地方使用它做日期转换是非常方便的,但是如果是放在一个大的循环内部,直接使用NSDateFormatter绝对不是明智的选择。它很有可能成为拖慢你程序速度的元凶。

其实如果你知道你的程序将会取得什么格式的日期字符串,那么直接分解字符串后利用NSCalendar和NSDateComponents可以提高速度很多。
- (NSDate*)mydateFromString:(NSString *)string;
{
//Wed Mar 14 16:40:08 +0800 2012
if (!string) return nil;
static NSCalendar *gregorian=nil;
static NSDateComponents *comps=nil;
static NSDictionary *month=nil;
if (gregorian==nil) {
gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
comps = [[NSDateComponents alloc] init];
month = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], @"Jan",
[NSNumber numberWithInt:2], @"Feb",
[NSNumber numberWithInt:3], @"Mar",
[NSNumber numberWithInt:4], @"Apr",
[NSNumber numberWithInt:5], @"May",
[NSNumber numberWithInt:6], @"Jun",
[NSNumber numberWithInt:7], @"Jul",
[NSNumber numberWithInt:8], @"Aug",
[NSNumber numberWithInt:9], @"Sep",
[NSNumber numberWithInt:10], @"Oct",
[NSNumber numberWithInt:11], @"Nov",
[NSNumber numberWithInt:12], @"Dec",
nil];
}

@try {
NSString *t=[string substringWithRange:NSMakeRange(26, 4)];
[comps setYear:[t intValue]];
t=[string substringWithRange:NSMakeRange(4, 3)];
[comps setMonth:[[month objectForKey:t] intValue]];
t=[string substringWithRange:NSMakeRange(8, 2)];
[comps setDay:[t intValue]];
t=[string substringWithRange:NSMakeRange(11, 2)];
[comps setHour:[t intValue]];
t=[string substringWithRange:NSMakeRange(14, 2)];
[comps setMinute:[t intValue]];
t=[string substringWithRange:NSMakeRange(17, 2)];
[comps setSecond:[t intValue]];
t=[string substringWithRange:NSMakeRange(20, 5)];
//全球共24个标准时区,每个时区为1个小时,下面计算该时区offset秒数
[comps setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:[t intValue]/100*3600]];
}
@catch (NSException *exception) {
}
@finally {
}

return [gregorian dateFromComponents:comps];
}

如果要更快,就需要抛弃ObjC,编写c代码格式化时间字符串。如下代码经过测试是最快的。
- (NSDate *)dateFromString:(NSString *)string {
//Wed Mar 14 16:40:08 +0800 2012
if (!string) return nil;
struct tm tm;
time_t t;
string=[string substringFromIndex:4];
strptime([string cStringUsingEncoding:NSUTF8StringEncoding], "%b %d %H:%M:%S %z %Y", &tm);
tm.tm_isdst = -1;
t = mktime(&tm);
return [NSDate dateWithTimeIntervalSince1970:t];
}

下面是我简单测试循环10000次解析日期字符串的时间比较。


2012-05-05 15:57:51.942 timetest[18488:707] 1.991521 //第一种
2012-05-05 15:57:52.096 timetest[18488:707] 0.921144 //第二种
2012-05-05 15:57:54.088 timetest[18488:707] 0.153897 //第三种
最后作为参考资料,说明一下 OSX 10.6 下 NSDateFormatter 使用 Unicode Locale Data Markup Language (LDML) version tr35-10 标准。作为标准文档,Apple是不会全部写到开发文档里的,不明白的同学可以到这查看。

原文地址:http://lianxu.me/blog/2012/03/14/speed-up-nsdateformatter/

 

 

转载于:https://www.cnblogs.com/jackyyang7/articles/2776541.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值