我正在使用一个包含日历的应用程序,我在特定日期添加了几个注释,并将日期和注释保存到plist,所以当我启动我的应用程序时,我从plist中检索日期并在日历日期显示带有颜色标记,以识别日期是否有注释。
当用户选择添加备注的日期时,我会以这种方式创建日期
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSMinuteCalendarUnit)fromDate:**date selected**];
NSInteger day = [weekdayComponents day];
NSInteger month = [weekdayComponents month];
NSInteger year = [weekdayComponents year];
NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init];
[timeZoneComps setDay:day];
[timeZoneComps setMonth:month];
[timeZoneComps setYear:year];
[timeZoneComps setHour:00];
[timeZoneComps setMinute:00];
[timeZoneComps setSecond:01];
NSDate *date = [gregorian dateFromComponents:timeZoneComps];
并将此日期保存到plist
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"file.plist"];
NSMutableDictionary *d = [NSMutableDictionary new];
[d setObject:date forKey:@"my-date"];
[d writeToFile:filePath atomically:YES];
现在,当我打开应用程序时,我会遍历我的日历日期并进行比较以标记不在日历上
这是
if([[**dateFromPlist** isEqualToDate:**dateFromCalendar**])
{
do something
}
当我在一个时区内写下和阅读日期时,这是有效的,但如果我写日期,假设我在10月-20日在印度时区(设备)创建了一个音符,然后我将时区更改为美国(设备)并打开我的应用程序,if条件永远不会执行,因为它会有不同的时间。
请帮我找出错误的地方。
此致 兰吉特。
答案 0 :(得分:4)
NSDate没有时区。它是unix时间的包装器,是自参考日期以来的浮点数秒。 (固定时间点)NSTimeInterval是double的typedef,是用于表示此浮点值的类型。
您应该做的是存储NSTimeInterval值。然后在从文件中读取NSDate对象时从该值创建NSDate对象。
时区严格地是向用户呈现的一部分。
假设someDate是NSDate
NSDate *someDate = [NSDate date];
NSTimeInterval someDateAsInterval = someDate.timeIntervalSinceReferenceDate;
好的,现在你有了你的双,a.k.a。NSTimeInterval。让我们将它保存到plist然后再读回来。我们将使用NSDictionary和NSNumber文字语法。 (我在这里不需要一个可变字典。)NSNumber是一种在标记中存储标量的好方法。
NSString *aFilePath = [@"~/Documents/my_fancy_file.plist" stringByExpandingTildeInPath];
NSDictionary *dateDict = @{@"dateAsInterval": @(someDateAsInterval)};
[dateDict writeToFile:aFilePath atomically:YES];
NSDictionary *dateDictFromFile = [NSDictionary dictionaryWithContentsOfFile:aFilePath];
NSTimeInterval dateFromFileAsTimeInterval = [dateDictFromFile[@"dateAsInterval"] doubleValue];
NSDate *dateFromFile = [NSDate dateWithTimeIntervalSinceReferenceDate:dateFromFileAsTimeInterval];
NSLog(@"\n someDate\n%@\n dateFromFile\n%@", someDate, dateFromFile);
下面的最后一点只是为了说明它有多方便。哦,我提到NSTimeInterval可能比完整的NSDate对象便宜很多吗?这是一个很好的加分。
if ([someDate isEqual:dateFromFile]) {
NSLog(@"SAME");
}
if (someDateAsInterval == dateFromFileAsTimeInterval) {
NSLog(@" == ");
}
现在还有一件事你完全搞砸了,但你并不孤单,而且不明显或不容易。 您可以从日期和时间中学到很多以下内容。文档中的时间编程指南。 其余内容在WWDC视频中有详细介绍。 事实上,人们已经搞砸了这么多,几乎每年都会在WWDC上报道。今年也没有例外。当你回想起NSDate实际上是一个包装typedef& d的对象,NSTimeInterval时,这将更容易理解。这提供了
让我们引用文档:
NSDate提供了创建日期,比较日期和方法的方法 计算间隔。日期对象是不可变的。标准单位 日期对象的时间是浮点值,键入为NSTimeInterval 并以秒表示。这种类型使广泛和 细粒度的日期和时间值范围,提供精确的内部 相隔10000年的日期的毫秒数。
这意味着该对象为您提供方法而不是C样式函数。一个可爱的Objective-C世界。支持数据结构NSTimeInterval为您提供了令人难以置信的精确度。
在最近的WWDC视频中还有一件事你需要知道。
比较日期和日历计算很难找到可能让您感到惊讶的原因。最值得考虑的是,并非所有日期都有午夜,有些日期不止一个! 因此,比较午夜的两个日期可能是一团糟。这很复杂但很真实。不要这样做。 最佳做法:白天使用一段时间,接近中午。所有日期都有这个时间,只有一次。 等等,我为什么要谈论时间?回头仔细思考。 NSDate的名字误导了很多人,我们插入了很多关于我们认为很简单的常见事物的假设,但实际上看起来很复杂。为方便起见,我们倾向于将日期视为日历上的日期,但事实上,日期和NSDate是特定的时间点。
事实证明,使用NSCalendar方法dateFromComponents是一个常见的错误:不包括更精细的组件。可悲的是,如果你没有提供时间,它会给你一个00:00:00的默认值,这会导致比较和计算的日期不可靠。
但我离题了。 这里的关键是使用您的NSTimeInterval值。这很容易比较。易于存放。很难出错。 您可以根据需要从中创建NSDate。 您可以根据需要使用当前区域设置显示它。
这是plist内容的样子。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>dateAsInterval</key>
<real>426751774.87438202</real>
</dict>
</plist>