【问题标题】:NSDate behaviour when saving to plist保存到 plist 时的 NSDate 行为
【发布时间】:2014-08-30 06:54:27
【问题描述】:

我正在从 [NSdate date] 创建一个日期并将其保存到 plist,这是我创建日期的方式

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
   // [gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];


    NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit  | NSMinuteCalendarUnit)fromDate:[NSDate date]];
    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];

    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];
}

我测试了几个案例

案例 1:没有将时区设置为上面的 NSCalendar 对象 gregorian(默认情况下它将采用本地时区)并将设备中的时区设置为印度,我将日期保存到 plist,这就是我得到的

强>

NSLog of date 显示 CurrentDate:2014-07-08 18:30:01 +0000

案例 2:现在将设备时区设置为美国圣何塞

NSLog 日期显示 2014-07-09 07:00:01 +0000

案例3:将NSCalendar对象的时区,上面的gregorian设置为“UTC”,并将设备中的时区设置为印度,这就是我在plist中得到的

NSLog 日期显示 2014-07-09 00:00:01 +0000

案例 4:将设备时间设置为美国圣何塞

NSLog 日期显示 2014-07-09 00:00:01 +0000

谁能解释一下在所有这些情况下发生了什么。

问候 兰吉特。

【问题讨论】:

  • +1 个结构良好的问题。当您使用 NSLog(@"date=%@", date); 记录日期对象时,您是否在控制台中获得相同的日期/时间?
  • 谢谢,在什么情况下?\
  • 那么上面的NSLog() 调用将使用[NSDate description] 打印日期,即UTC 日期。因此,您已经证明了使用特定时区设置日期并将其保存为 UTC 的效果,这就是 plist 中日期更改的原因。
  • @trojanfoe,当时区是 UTC 并且设备时区是 san jose 时,为什么在 plist 中是上午 5:30:01,我可以理解印度地区,因为偏移量是 UTC+5 :30.
  • 呃,老实说我不明白。您的代码可能有错误(印度和加利福尼亚的时间相同,所以这里有问题)。

标签: ios nsdate plist nsdatecomponents nstimezone


【解决方案1】:

这是因为您处理NSDate 的方式。一旦您将某些内容转换为NSDate,那么您将丢失所有时区信息,并且当您将其写入 plist 时,它将被写入 您当前的时区,因为它被转换回字符串。因此,让我们一一浏览场景。

所有场景都遵循这个流程 NSDate -> NSDateComponents -> NSDate -> 字符串

1) NSDate: 2014-07-09 XX:XX:XX IST -> NSDateComponents 2014-07-09 00:00:01 IST -> NSDate 2014-07-09 00 :00:01 IST -> 2014 年 7 月 9 日上午 12:00:01

2) NSDate: 2014-07-09 XX:XX:XX PST -> NSDateComponents 2014-07-09 00:00:01 PST -> NSDate 2014-07-09 12 :30:01 IST -> 2014 年 7 月 9 日下午 12:30:01

3) NSDate: 2014-07-09 XX:XX:XX UTC -> NSDateComponents: 2014-07-09 00:00:01 UTC -> NSDate: 2014-07- 09 05:30:01 IST -> 2014 年 7 月 9 日上午 5:30:01

4) 与 3 相同,因为您手动指定了时区

请记住NSDate 不关心时区。这只是一个时间点。 2014-07-09 00:00:01 UTC 和 2014-07-09 05:30:01 IST 确切 NSDate 的条款(格林威治标准时间 2001-01-01 00:00:00 前 426556801 秒)。它们在 plist 中不同的原因是因为您正在(隐式)选择 NSDate 的本地时间表示。如果您需要更多控制权,请使用NSDateFormatter

编辑想一想,您可能会争辩说结果应该不同,但NSDate 输出到 plist 的方式是专有的,因此看起来由于某种原因它一直使用印度语标准时间。推测可能包括您可能没有在设置时区或其他东西之间杀死您的应用程序。

第二次编辑实际上我对原始 plist 的内容很感兴趣。您正在使用编辑器查看它,它可能会在显示时将其转换为您的 Mac 的本地时间。

【讨论】:

  • 嘿@borrrden,感谢您提供详细信息,我通过卸载应用程序并再次运行进行测试,但结果也相同,所以我认为您的猜测不成立。
  • 您说要获得更多控制权,请使用 NSDateFromatter,但这在哪里出现,bcoz,我只保存日期,我没有将它们转换为字符串
【解决方案2】:

NSDate 代表绝对时间点,与时区无关。您看到和记录的是NSDate 描述,它在不同情况下相当随意,并且根据Apple Docs

的调试有用

该表示仅对调试有用。

有许多选项可以获取日期的格式化字符串 包括:日期格式化程序(参见 NSDateFormatter 和数据格式化 指南),以及 NSDate 方法 descriptionWithLocale:, dateWithCalendarFormat:timeZone:, 和 descriptionWithCalendarFormat:timeZone:locale:

因此,您可以将您的 NSDate 保存为存储状态,因为它独立于任何时区信息,并使用 NSCalendarNSDateFormatter 进行应用所需的所有转换。

【讨论】:

  • 那么你的意思是如果我的应用被美国用户使用,那么 plist 将包含他/她存储的日期的上午 5:30:01?
  • 不一定,但对你没有任何影响。 NSDate 将始终指向同一时间点。因此,正如我在上面所写的,您只需使用 NSCalendarNSDateFormatter 检索它并将其转换为所需的格式
  • 所以你这么说,plist 包含 5:30:01 还是 12:30:01 都没有关系,对吧?因为第二种情况是12:30:01
  • 我认为@borrrden 的回答很好地总结了它。
猜你喜欢
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
相关资源
最近更新 更多