【问题标题】:NSDateComponent setHour is not setting correctly [duplicate]NSDateComponent setHour 设置不正确[重复]
【发布时间】:2013-05-17 14:58:00
【问题描述】:

我正在尝试创建一个时间设置为上午 12:00:01 的日期。秒和分钟正确设置为它们的值,但小时值总是变为我设置的值,+ 4。为什么是 4?这个值有什么特别之处?分钟和秒值设置为我想要的正确值,但似乎小时值只是添加而不是替换。

这里是代码,

        NSDate *now = [NSDate date];
        NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
        NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
        [components setHour:0];
        [components setMinute:0];
        [components setSecond:1];

        NSDate *compareTime = [calendar dateFromComponents:components];
        NSLog(@"compareTime: %@", compareTime);
        NSLog(@"currentTime: %@", now);

输出是:

比较时间:2013-05-17 04:00:01 +0000

当前时间:2013-05-17 15:00:37 +0000

【问题讨论】:

  • 这可能是您的本地时间和 UTC 之间的差异。你在哪个时区?
  • 我在美国东部时间。但为什么会有所作为呢?无论时区如何,0 都应为 0。它实际上是在尝试自动调整吗?如果是这样,我需要做什么才能解决这个问题?
  • 默认情况下,[NSDate date] 会为您提供原始日期,并且不假定本地时区。
  • 我知道它给了我一个原始日期,但如果我将小时硬编码为 0,为什么它不为零?
  • 令人惊讶的是,许多开发人员不了解时间和时区。时间就是时间;它是一种测量。时区告诉如何格式化时间。美国东部标准时间下午 4:00 与太平洋标准时间下午 4:00 不同。

标签: iphone ios objective-c


【解决方案1】:

EST 比 GMT 早 4 小时,因此您的偏移量。这是我们用来创建日期加上和减去本地时区的当前时间的一些代码。

- (NSDate *) getDateWithHoursOffset : (int) aHourInt
{
CFGregorianDate gregorianStartDate, gregorianEndDate;
CFGregorianUnits startUnits = { 0,0,0, aHourInt,0,0 }; //2 hours before
CFGregorianUnits endUnits   = { 0,0,0, 8,0,0 }; //5 hours ahead
CFTimeZoneRef timeZone = CFTimeZoneCopySystem();

gregorianStartDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTimeGetCurrent(), timeZone, startUnits),timeZone);
gregorianStartDate.minute = 0;
gregorianStartDate.second = 0;

gregorianEndDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTimeGetCurrent(), timeZone,   endUnits),timeZone);
gregorianEndDate.minute = 0;
gregorianEndDate.second = 0;

NSDate* startDate = [NSDate dateWithTimeIntervalSinceReferenceDate:CFGregorianDateGetAbsoluteTime(gregorianStartDate, timeZone)];
CFRelease(timeZone);
return startDate;
}

【讨论】:

    【解决方案2】:

    NSDate 独立于时区而存在。如果您需要在应用程序中显示 12:00:01 的日期,则应使用 NSDateFormatter。

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeStyle:NSDateFormatterFullStyle];
    
    NSLog(@"formattedTime: %@", [dateFormatter stringFromDate:compareTime]);
    

    这会返回:

    formattedTime: 12:00:01 AM Central Daylight Time
    

    【讨论】:

      【解决方案3】:

      问题是您的日期是正确的,但它们是以相对于您设备的时区的 UTC 登录的,这似乎令人困惑。 (一开始是这样)

      您的比较时间是正确的。它设置为您的时间午夜并输出为 UTC,如果您是 EST 午夜将是凌晨 4 点 UTC:

      compareTime: 2013-05-17 04:00:01 +0000

      当前时间也是正确的,同样是相对于您设备时区的 UTC 时间:

      currentTime: 2013-05-17 15:00:37 +0000

      你的时间是正确的,它是在欺骗你的输出。

      此代码(可耻地从下面列出的线程中窃取)应将compareTime 的UTC 日期输出为00:00:01 +0000。虽然对于日期计算 UTC 应该没问题。

      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:compareTime];
      

      这里有一些 S.O.有助于进一步解释的线程:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-26
        • 2016-11-06
        • 1970-01-01
        • 1970-01-01
        • 2017-05-14
        • 2011-03-23
        • 2012-03-27
        相关资源
        最近更新 更多