ios - 为什么 NSDateComponents 给我一个不同的日期?

标签 ios objective-c

代码如下:

NSDate *dateLocalNow = [self getLocalDate:[NSDate date]];
NSLog(@"%@",dateLocalNow);

NSDateComponents *dateToCheckAgainst = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit | NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSMinuteCalendarUnit fromDate: dateLocalNow];
NSLog(@"%@", dateToCheckAgainst);

getLocalDate 给我本地时区的日期。如果 dateLocalNowNSLog 输出:

2014-10-29 01:01:55 +0000    

这是 getLocalDate 来源:

-(NSDate *)getLocalDate:(NSDate *)date {
NSDate* sourceDate = date;

NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];

NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;

NSDate* destinationDate = [[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate];
return destinationDate;
}

为什么 NSLog for dateToCheck against 给我以下信息?:

Calendar Year: 2014
Month: 10
Leap month: no
Day: 28
Minute: 1

最佳答案

NSDate 与时区无关。在内部,它存储自引用时间点以来经过的秒数。该引用点有许多人类可读的标签。以下是 Cocoa 标准引用日期的一些人类可读标签:

  • 1/1/01,格林威治标准时间上午 12:00:00
  • 12/31/00,下午 6:00:00 CST
  • 1/1/01,格林威治标准时间+4 上午 4:00:00

这些标签都代表同一时刻,但可以用许多不同的方式来标记该时刻。只有一种方法可以将该瞬间表示为 NSDate

您已经创建了一个新的 NSDate,它是原始的 NSDate,调整了一些时区偏移量,但 iOS SDK 不知道也不关心。它认为您的新 NSDate 是基于其标准引用日期的偏移量的即时时间。该新时刻与您的原始时刻不同(除非您的系统时区恰好是 GMT)。你不应该期望它在转换为人类可读的字符串或 NSDateComponents 时产生相同的结果,除非你在 NSDateFormatter 上设置时区NSCalendar 恰到好处——您在发布的代码中没有这样做。

那你怎么办呢?您不要尝试创建一个 NSDate,该 NSDate 与另一个基于时区偏移的 NSDate 存在偏移。相反,当您将 NSDate 转换为人类可读的字符串时,您可以通过设置 NSDateFormattertimeZone 属性来指定时区。或者,当您询问日期的组成部分时,您可以设置 NSCalendartimeZone 属性。如果您从组件构建日期,您还可以在使用日历将组件转换为 NSDate 之前设置 NSDateComponentstimeZone >.

因此:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSDate *now = [NSDate date];

        NSDateFormatter *f = [[NSDateFormatter alloc] init];
        f.dateStyle = NSDateFormatterShortStyle;
        f.timeStyle = NSDateFormatterLongStyle;
        f.timeZone = [NSTimeZone systemTimeZone];
        NSLog(@"from formatter = %@", [f stringFromDate:now]);

        NSCalendar *calendar = [NSCalendar currentCalendar];
        calendar.timeZone = [NSTimeZone systemTimeZone];
        NSDateComponents *components = [calendar components:NSMinuteCalendarUnit | NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
        NSLog(@"components = %@", components);
    }
    return 0;
}

输出:

2014-10-29 00:24:19.762 commandline[28543:303] from formatter = 10/29/14, 12:24:19 AM CDT
2014-10-29 00:24:19.763 commandline[28543:303] components = <NSDateComponents: 0x1001027a0>
    Calendar Year: 2014
    Month: 10
    Leap month: no
    Day: 29
    Minute: 24

关于ios - 为什么 NSDateComponents 给我一个不同的日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26623118/

相关文章:

ios - 关于Objective-C或iOS中的内存管理

ios - 启动失败。该应用程序无法在 xamarin 上启动

ios - UITableViewCells 向下滚动时滚动到标题

ios - 过滤器功能在这种情况下不起作用?

ios - 获取 UITableViewCell 的高度

ios - 我没有看到底栏按钮...(使用 Xcode 5.1.1)

ios - gameOverScene 中使用 admob 的插页式广告

ios - Xcode 8 本地化导入崩溃

objective-c - 在 block 内访问 C 数组(可变数组计数)Objective-C

ios - 用户个人资料图片是 jpg 还是 png?