Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSDate在与NSString转换后不相等_Ios_Objective C - Fatal编程技术网

Ios NSDate在与NSString转换后不相等

Ios NSDate在与NSString转换后不相等,ios,objective-c,Ios,Objective C,我正在尝试在JSON中存储和检索日期。从相同字符串创建的NSDATE失败isEqualToDate:。这当然是由于浮点精度问题,但我不确定如何解决它 给dateFromString:给定两个相同的输入字符串,得到的NSDate对象应该相等: NSDate *date1 = [NSDate date]; NSString *string1 = [dateFormatter stringFromDate:date1]; NSDate *dateA = [dateFormatter dateFromS

我正在尝试在JSON中存储和检索日期。从相同字符串创建的NSDATE失败
isEqualToDate:
。这当然是由于浮点精度问题,但我不确定如何解决它

dateFromString:
给定两个相同的输入字符串,得到的
NSDate
对象应该相等:

NSDate *date1 = [NSDate date];
NSString *string1 = [dateFormatter stringFromDate:date1];
NSDate *dateA = [dateFormatter dateFromString:string1];
NSDate *dateB = [dateFormatter dateFromString:string1];
XCTAssertTrue([dateA isEqualToDate:dateB]);
…但是,实际上,由于浮点精度问题引入了随机积垢,结果日期对象幸运地相等(而且很少相等):

(lldb) p [dateA timeIntervalSinceReferenceDate]
(NSTimeInterval) $4 = 560455653.79073596
(lldb) p [dateB timeIntervalSinceReferenceDate]
(NSTimeInterval) $5 = 560455653.79099989
那么,有人遇到这种情况并解决了它吗?我想到的唯一选择是编写自己的
isEquals:
,但这并不理想


编辑:

具体来说,我要寻找的是一种将日期的字符串表示形式转换回日期对象的方法,对于相同的输入字符串,该对象将被视为相等

<代码>(Netrase<代码> >存储在浮点数中的内部状态是不相关的,因为在给定相同输入时,基础应该提供一种机制来实现输出日期的奇偶性(即相同的字符串应该产生相等的对象)。两个基金会都提供了这一点,我很怀念(希望这样的社区知道一些关于基金会的事情我不知道),或者基金会是BGGY(在这种情况下),我正在寻找这样一个社区,我还没有考虑过这个问题。 编辑2:

对不起,我的问题,正如最初问的,是胡说八道。为了简化这篇文章的问题,我无意中对两个不可能相等的数字进行了比较

原版胡说八道帖子,面向子孙:

我正在尝试在JSON中存储和检索日期。存储到JSON中的
NSDate
I在从存储字符串重新创建的
NSDate
对象上失败
isEqualToDate:
。这当然是由于浮点精度问题,但我不确定如何解决它。 具体而言:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
dateFormatter.locale = [[NSLocale alloc]
initWithLocaleIdentifier:@"en_US_POSIX"];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
NSDate *date1 = [NSDate date];
NSString *string1 = [dateFormatter stringFromDate:date1];
NSDate *date2 = [dateFormatter dateFromString:string1];
NSString *string2 = [dateFormatter stringFromDate:date2];
// This test passes
XCTAssertTrue([string1 isEqualToString:string2]);
// This test fails
XCTAssertTrue([date1 isEqualToDate:date2]);
// This test fails
XCTAssertTrue([date1 isEqual:date2]);
查看调试器中的
date1
date2
,我们看到了区别:

(lldb) p [date1 timeIntervalSinceReferenceDate]
560363055.21521103

(lldb) p [date2 timeIntervalSinceReferenceDate]
560363055.21499991
(注意第千位)

NSDate
isEqual:
(和variant)几乎肯定是在比较 实例的时间偏移,因此失败

我已尝试为存储的字符串添加更高的精度(即。
.SSSSSS
)但这似乎没有影响

那么,有人遇到这种情况并解决了它吗?我唯一的选择 我的想法是写我自己的
isEquals:
,但这并不理想


tl;dr-您正在尝试将纳秒与毫秒进行比较。这些结果将不一样

使用
[NSDate date]创建
NSDate
得到的值包括小数秒,精度为微秒,甚至纳秒

将日期转换为格式为
yyyy-MM-dd'T'HH:MM:ss.SSS
的字符串时,创建的字符串正好有3位小数(毫秒)。然后,当您将该字符串转换回一个
NSDate
时,您将得到一个浮点数,该浮点数尽可能接近这些毫秒

因此,原始日期的精度为微秒或纳秒,而第二个日期的精度仅为毫秒。当然,由于精度不同,这两个日期会有所不同。这与浮点数无关。即使您有完美的浮点数,您也将100.123456789与100.123进行比较。他们不是同一个数字

您声明您尝试使用
SSSSSS
而不是
SSS
,但是
NSDateFormatter
不支持超过三个小数位数的内容,因此
SSS
之外的内容都是白费力气

有了这个解释,你有什么办法来比较你的两次约会

一种是将两个日期仅与小数点后三位进行比较。下面是一个有用的小
NSDate
category方法,它可以:

@interface NSDate (extra)

- (BOOL)isEqualToDateMilliseconds:(NSDate *)otherDate;

@end

@implementation NSDate (extra)

- (BOOL)isEqualToDateMilliseconds:(NSDate *)otherDate {
    TimeInterval secs1 = [self timeIntervalSinceReferenceDate];
    TimeInterval secs2 = [self timeIntervalSinceReferenceDate];

    return abs(secs1 - secs2) < 0.001;
}

@end
与:


您将得到正确的结果。

因为底层存储的NSDates是一个浮点数,我认为没有任何方法可以在不损失精度的情况下使用NSDateFormatter。如果希望能够使用isEqualToDate:可以尝试使用timeIntervalSinceReferenceDate(或timeIntervalSince1970)将日期存储为浮动。但问题是isEqualToDate:只能告诉你,如果两个日期足够接近,任何差值都小于浮点数所表示的差值,这真的是你想要将其视为相等的,还是如果两个日期相距小于一秒或一毫秒,你更愿意将其视为相等的,我可以想象,在某些情况下,您确实希望使用isEqualToDate:但是,您应该使用timeIntervalSinceReferenceDate而不是NSDateFormatter,这是一种解析和生成人类可读字符串的方法,而不是以有损格式存储数据。

出于平等考虑,比较无效,从系统时钟创建的
NSDate
,以及以这种方式从字符串重构的
NSDate
。这就像问“为什么一个浮点数不保存为字符串,保留到小数点后3位,并转换回与原始浮点数相等的浮点数?”你不应该对重新组合的日期和时钟派生的日期执行相等性测试。它本质上就像任何其他基于浮点的比较一样。您的方法无法按预期工作。两个浮点值之间的间距可以小于1/1000,但在不同方向上仍然是圆的。使用
fabsf(a-b)<0.001
。您能否引用您对
NSDateFormatter
不尊重额外精度的评论?我看到苹果的文档引用了这个文档,它为
s
格式说明符的数量提供了
1-n
(意味着没有限制)。是的,我知道我可以实现我自己的
isEqua
XCTAssertTrue([date1 isEqualToDate:date2]);
XCTAssertTrue([date1 isEqualToDateMilliseconds:date2]);