【问题标题】:NSDate - Offsetting the Time ZoneNSDate - 偏移时区
【发布时间】:2011-01-05 18:39:15
【问题描述】:

我一定是错过了她的一些小事,但我想不通。试图创建一个日期进行比较,但我似乎无法将 currentDate 从 GMT 偏移到 EST:

// current date (gmt) //
NSDate *currentDate = [NSDate date];

NSTimeZone *currentDateTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"EST"];

NSDateFormatter *currentDateFormat = [[NSDateFormatter alloc]init];
[currentDateFormat setTimeZone:currentDateTimeZone];
[currentDateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];

NSString *currentDateString = [currentDateFormat stringFromDate:currentDate];
NSLog(@"currentDateString: %@", currentDateString); // returns 2011-01-05 13:30:30 EST

NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];

NSLog(@"currentDateWithOffset: %@", currentDateWithOffset); // returns 2011-01-05 18:30:30 +0000

谢谢!

编辑:

我正在使用以下行在单独的类中调用一个方法(试图使其可移植):

[Expiration expires:[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 +0000"] within:1.0]

在 expires 方法中,我有以下几行:

NSComparisonResult comparison = [currentDateWithOffset compare:expires]; // check for a fixed date to disable the demo

double withinRange = [installDate timeIntervalSinceDate:currentDateWithOffset]; // check for number of seconds between "within" and the install date

然后我像这样比较这两个值:

if(withinRange >= within && withinRange > 0.0) {
    // app is expired //
}
else {
    // app is still enabled (so far...) //
    if(comparison == NSOrderedDescending || comparison == NSOrderedSame) {
        // app is expired //
    }
    else {
        // app is still enabled //
    }
}

这有帮助吗?感谢您的耐心等待!

编辑:

这里是整个 expires:within 方法,因为它目前的状态......

+(BOOL)expire:(NSDate*)expires within:(double)within {
   // default expired value //
    BOOL expired = NO;

    // convert within value from days to seconds //
    within *= 24.0 * 60.0 * 60.0;

    // current date (gmt) //
    NSDate *currentDate = [NSDate date];

    // install date //
    NSDate *installDate = [[NSUserDefaults standardUserDefaults]objectForKey:@"installDate"];

    // check for a value in installDate //
    if (nil == installDate) {
        // app is running for the first time //
        [[NSUserDefaults standardUserDefaults]setObject:currentDate forKey:@"installDate"];
        [[NSUserDefaults standardUserDefaults]synchronize];
        installDate = currentDate;
    }

    if([installDate timeIntervalSinceNow] < (-within)) {
        expired = YES;
    }
    else {
        if([expires timeIntervalSinceNow] < 0) {
            expired = YES;
        }
    }

    NSLog(@"installDate:%@", installDate);
    NSLog(@"expires:%@", expires);
    NSLog(@"currentDate:%@", currentDate);

    return expired; 
}

然后我用

从另一个类调用它
message.text = (YES == [Expiration expire:[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 -0500"] within:(0.015625/2)]) ? @"This App is Expired" : @"This App is Active";

在模拟器中运行时(新应用安装),NSLog 显示这个...

[Session started at 2011-01-06 10:43:46 -0500.]
2011-01-06 10:43:48.146 TimeBasedDemo[14717:207] installDate:2011-01-06 15:43:48 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] expires:2011-01-07 17:00:00 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] currentDate:2011-01-06 15:43:48 +0000

【问题讨论】:

  • 您能否更具体地说明您真正想要做什么?
  • 我正在尝试将当前日期/时间与提供的限时演示应用程序的日期/时间进行比较。给我带来麻烦的部分是在我的时区(EST)而不是 GMT 进行比较。调用包含方法时,使用我自己的时区比转换为 GMT 更容易。
  • 该代码看起来完全正确,输出也是如此。我猜您的问题是您希望在日志中看到10:43:48 -0500 而不是15:43:48 +0000。问题是——没关系。它们同时。当你调用 NSLog 时,它就是这样打印出来的。
  • 好吧,我现在感觉自己像个真正的白痴...... NSLog 在应用偏移量 -0500 后,在 GMT 时打印过期。我期待看到它是 07:00:00。我想我现在明白了。感谢您所有的帮助。现在我只需要弄清楚如何让它在使用应用程序时调用此方法。再次感谢!
  • P.S.我想出了如何让最后一部分如何工作,这样可以节省一个新线程!

标签: objective-c nsdate


【解决方案1】:

这些答案都没有给我一个带有当前本地日期的NSDate 对象。所以我是这样做的:

NSDate *currentDateWithOffset = [NSDate dateWithTimeIntervalSinceNow:[[NSTimeZone localTimeZone] secondsFromGMT]];

【讨论】:

  • 我已经离开了!感谢您的回答!
【解决方案2】:

NSDate 对象代表一个瞬间,与时区和日历无关。当您打印或解析日期时,时区信息是相关的,但它不存储在NSDate

假设您正在创建这样的到期日期:

NSDate *exp=[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 +0000"]

这表示您希望在格林威治标准时间 1 月 7 日中午到期。如果您希望它在美国东部标准时间中午到期,请改为使用 -0500 创建它。您应该做的是在进行比较时弄乱当前时间。

一个简单的方法就是看看时间是否过去

if ([exp timeIntervalSinceNow]<0) { /* it's expired */ }

你可以看到within自安装日期以来是否已经过去了,如下所示:

if ([installDate timeIntervalSinceNow]<(-within)]) { /* it's expired */}

【讨论】:

  • 谢谢,不变!这有助于清理(和清除)一些东西,谢谢。不幸的是,我仍然遇到时区问题。 installDate 是使用 currentDate (NSDate *currentDate = [NSDate date];) 设置的,因此在比较过程中仍然存在差异。由于目标是在不编辑的情况下重用类,并允许时区偏移,NSDate 是真正实现这一目标的方式吗?
  • 我确信 NSDate 是正确的方法,我自己也是这样做的。我认为您误解了 NSDate 的工作原理。如果您使用[NSDate date] 记录安装日期,将其存储,然后稍后再与[NSDate date](或timeIntervalSinceNow)进行比较,那么它将始终为您提供这些方法之间的经过时间称为。时区根本不会出现,它只是当您显示它或将其存储为字符串时的一个符号。我在自己的代码中做同样的事情,没有任何问题。
  • 我想我还是不明白。我在上面进行了编辑以显示 NSLog 的代码和结果...
【解决方案3】:

在 Cocoa 中,NSDate 是没有应用时区信息的日期的抽象表示。请注意,currentDateWithOffset 与日期字符串相同的日期,只是在不同的时区(提前五个小时)。这是预期行为,因为NSDate 不会保留用于创建它的时区。

【讨论】:

    【解决方案4】:

    我进行了更多修改,并找到了一种“欺骗”偏移量以满足我的需求的方法。从其他阅读中,我猜 NSCalendar 可能是一个更好的长期解决方案,但现在我最终改变了

    NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];
    

    NSDate *currentDateWithOffset = [[NSDate alloc] initWithString:[NSString stringWithFormat:@"%@ +0000", currentDateString]];
    

    这让我得到了我需要的结果,并且可以在我以后使用的比较中使用。感谢大家提供背景信息!

    【讨论】:

    • 您最好努力正确地创建参考日期,这样您就不必调整当前日期以使其正常工作。
    • 我会想办法做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多