在Objective-C(iPhone OS SDK)中解析ISO8601日期

7
我该如何将“2010-04-30T00:45:48.711127”解析为NSDate?(并保留所有精度)

1
可能是通过Cocoa的NSDate解析不支持的日期格式的重复问题。 - Nicholas Riley
1
提示:就你的问题而言,它是含糊不清的——并不完全清楚你是在问有关Cocoa的“初学者”问题(“如何解析给定格式的日期”),还是高级问题。根据你对答案的评论,你是在问高级版本。既然如此,如果你包括一条注释,比如“我知道NSDateFormatter可以用于这种格式,但它的精度提前了三个位置”,那么你可能会得到更少的答案噪音。 - Ben Zotto
3个回答

4
你的工作很有难度。
对于秒数超过3位小数点的值,NSDate会将其舍去。你可以创建NSDate的子类来保存这些精度,但是你还需要实现自己的解析和自定义格式化程序来输入和显示它,因为NSDateFormatter和建立在其基础上的CFDateFormatter也会在3位小数点后截断精度。不过,根据你的需求,这并不应该太难。
这是一个简单的子类(没有实现NSCodingNSCopying),可以保留所有给定的精度。
@interface RMPreciseDate : NSDate {
    double secondsFromAbsoluteTime;
}

@end

@implementation RMPreciseDate

- (NSTimeInterval)timeIntervalSinceReferenceDate {
    return secondsFromAbsoluteTime;
}

- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded {
    if (!(self = [super init]))
        return nil;

    secondsFromAbsoluteTime = secsToBeAdded;

    return self;
}

@end

您可以请求-timeIntervalSince1970以获取UNIX纪元时间。

已经有一个ISO8601日期/时间解析器类,但由于它使用NSDateComponents来生成其日期,目前仅限于完整的秒精度,但您可以将其用作起点,以创建更精确的表示。


0

-1

看起来NSDate只有毫秒精度。

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'hh:mm:ss.SSSSSS"];

    NSDate *date = [dateFormatter dateFromString:@"2010-04-30T00:45:48.711127"];

    NSLog(@"%@", date);

    NSString *string = [dateFormatter stringFromDate:date];

    NSLog(@"%@", string);

    [pool drain];
    return 0;
}

该代码将产生以下控制台输出:

Program loaded.
run
[Switching to process 27202]
Running…
2010-05-08 20:02:46.342 TestNSDate[27202:a0f] 2010-04-30 00:45:48 -0700
2010-05-08 20:02:46.344 TestNSDate[27202:a0f] 2010-04-30T12:45:48.711000

Debugger stopped.
Program exited with status value:0.

所以"2010-04-30T00:45:48.711127"变成"2010-04-30T00:45:48.711000"可能不是你想要的。


看起来我们都卡在了同一个点上。我认为问题可能出在NSDateFormatter上,因为在许多地方都有记录显示NSDate支持微秒精度。 - bradley.ayers
有 NSTimeInterval 具有这种能力。也许需要使用组合模式... - WineSoaked
也许我应该更具体地说明:将这些亚毫秒分辨率的时间戳(缺乏更好的描述)存储在NSDate本身中有多重要?一个处理微秒分辨率的子类是否可以弥补您需要的额外精度差异? - WineSoaked
1
你的代码有一个小错误。你应该将格式更改为yyyy-MM-dd'T'HH:mm:ss.SSSSSS(注意使用HH而不是hh),因为ISO格式中的时间使用24小时制而不是12小时制。 - Piotr Czapla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接