4

我搜索了我的问题,但没有找到任何相关的帮助...

故事:用户按名称、开始日期、结束日期和注释创建一个继续事件,因此将所有字段保存在 Sqlite 数据库中。两种日期格式均为“yyyy-MM-dd”。之后,当用户想要对事件执行操作时,应用程序会检查用户通过开始和结束日期选择的日期,以及输入的日期是在开始日期之前还是在结束日期之后通知用户。

问题:作为用户,我创建了一个从 18-8-2012 到 18-9-2012 的事件。然后我在 2012 年 8 月 18 日登录并收到通知。我调试了应用程序。我很惊讶。格式为“yyyy-MM-dd”的字符串中的日期对象是“2012-08-17 19:30:00 +0000”。代码是:

           #define kPickerDate @"yyyy-MM-dd"
           NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
           [formatter setDateFormat:kPickerDate];
           NSDate *sDate = [formatter dateFromString:start_date]; 
           NSDate *eDate = [formatter dateFromString:exam_date]; 

应用程序如何????????????????

4

2 回答 2

10

AnNSDate不仅仅是一个日期,也是一个时间。

您需要在每个阶段进行检查:

  • 解析时您的日期是否正确构建?它应该是 UTC 午夜,而不是本地午夜。您可能正在NSDateFormatter为此使用 a 。确保它的时区设置为 UTC。
  • 您的日期是否正确存储在 SQLite 中?同样,请确保将其存储为 UTC。但是,如果您正确解析它,则应该可以。
  • 您是否正确格式化输出? 可能NSDateFormatter为此使用 a 。确保它的时区设置为 UTC。

只有当所有三个部分都完美时,您才能在这里摆脱潜在的错误。

要设置日期格式化程序的时区,请使用:

formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"];

不要试图通过采用当地时间来解决这个问题。

当地时间的问题:

  • 在许多时区,时间每年会随着夏令时变化几次。一小时的差异会将您时间的日期部分抛到前一天!
  • 如果用户处于没有夏令时的时区,他们可能会前往不同的时区。同样,您的时间中的日期部分可能会被丢弃一天。

唯一安全的做法是在任何地方使用 UTC。

(实际上我有点同情住在 UTC 的人;他们没有被迫从他们的应用程序中清除这些错误!)

于 2012-08-29T19:55:13.213 回答
1

您可以使用更好的方法创建 NSDate 对象。首先修改 NSDate 的@interface(你可以在任何地方这样做)。为此,请将其放在头文件中。

@interface NSDate (missingFunctions) 
+ (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;
@end

然后在主文件中放:

@implementation NSDate (missingFunctions)
+ (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setYear:year];
    [components setMonth:month];
    [components setDay:day];

    //BUT MOST IMPORTANTLY:
    [components setTimeZone:[NSTimeZone localTimeZone]];
    [components setHour:hour];
    [components setMinute:minute];
    [components setSecond:second];

    return [calendar dateFromComponents:components];
}   
@end

然后从代码调用中的任何地方(例如):

[NSDate dateWithYear:1969 month:8 day:15];

它将根据您的请求在正确的时区返回 NSDate。您还可以通过阅读官方苹果文档中有关NSTimeZone的更多信息来更改要使用的时区。

请注意,我不能因为编写此代码而受到赞扬,但我可以保证它可以正常工作。

于 2012-08-29T19:47:57.650 回答