Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNumber from NSDate

I'm attempting to get around a date validation that refuses to take anything earlier than tomorrow.
So far I have this:

NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
                // Negative one day, in seconds (-60*60*24)
NSLog(@"%@", [NSDate date]);
    // "yyyy-MM-dd HH:mm:ss Z", accurate assuming Z = +0000
NSLog(@"%@", dateY);
    // "yyyy-MM-dd HH:mm:ss Z", same accuracy (minus one day)

That's great, but dateY is not an NSNumber. I need an NSNumber for the comparison, but I can't find anything that works. (I don't even know how an NSNumber can be 2011-04-14 13:22:29 +0000, anyway...)

I can use NSDateFormatter to convert an NSDate into an NSString, so if it would be possible to take that string and convert it to the required NSNumber (as opposed to directly converting the NSDate to an NSNumber, which I can't seem to find help with either), that would be fine.


- (BOOL)validateDueDate:(id *)ioValue error:(NSError **)outError {
    NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
    NSNumber *tis1970 = [NSNumber numberWithDouble:[dateY timeIntervalSince1970]];
    NSLog(@"NSNumber From Date : %@", tis1970);
    NSLog(@"Date From NSNumber : %@", [NSDate dateWithTimeIntervalSince1970:[tis1970 doubleValue]]);

    // Due dates in the past are not valid
    // Enforced that a due date has to be >= today's date
    if ([*ioValue compare:[NSDate date]] == NSOrderedAscending) {
        if (outError != NULL) {
            NSString *errorStr = [[[NSString alloc] initWithString:@"Due date must be today or later."] autorelease];
            NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObject:errorStr forKey:@"ErrorString"];
            NSError *error = [[[NSError alloc]
                                initWithDomain:TASKS_ERROR_DOMAIN
                                code:DUEDATE_VALIDATION_ERROR_CODE
                                userInfo:userInfoDictionary] autorelease];
            *outError = error;
            }
        return NO;
    } else {
        return YES;
    }
}

Right now, the user is not allowed to choose a date before tomorrow. errorStr lies. Before today makes more sense than before tomorrow as a rule for refusing to save the date, so I've been fighting with this thing to let me use yesterday in place of today, rather than looking any deeper.

Edit: Using NSOrderedSame allows any date to be selected without an error. That won't do.

like image 728
Thromordyn Avatar asked Apr 14 '11 13:04

Thromordyn


3 Answers

You can convert an NSDate to an NSNumber like this:

NSDate *aDate = [NSDate date];
NSNumber *secondsSinceRefDate = [NSNumber numberWithDouble:[aDate timeIntervalSinceReferenceDate]];

and convert back like:

aDate = [NSDate dateWithTimeIntervalSinceReferenceDate:[NSNumber doubleValue]];
like image 112
odrm Avatar answered Nov 15 '22 22:11

odrm


All that is needed to get a NSNumber is

NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
NSNumber *tis1970 = [NSNumber numberWithDouble:[dateY timeIntervalSince1970]];
NSLog(@"NSNumber From Date : %@", tis1970);
NSLog(@"Date From NSNumber : %@", [NSDate dateWithTimeIntervalSince1970:[tis1970 doubleValue]]);
like image 22
Joe Avatar answered Nov 15 '22 23:11

Joe


You should never use 86400 to calculate date differences, because not all days have 86,400 seconds in them. Use NSDateComponents instead:

- (BOOL)validateDueDate:(NSDate *)dueDate error:(NSError *)error {
  NSDate *today = [NSDate date];
  NSCalendar *calendar = [NSCalendar currentCalendar];
  NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:today];
  //adjust the components to tomorrow at the first instant of the day
  [components setDay:[components day] + 1];
  [components setHour:0];
  [components setMinute:0];
  [components setSecond:0];
  NSDate *tomorrow = [calendar dateFromComponents:components];

  NSDate *earlierDate = [dueDate earlierDate:tomorrow];
  if ([earlierDate isEqualToDate:dueDate]) {
    //the dueDate is before tomorrow
    if (error != nil) {
      NSString *errorStr = [[[NSString alloc] initWithString:@"Due date must be today or later."] autorelease];
      NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObject:errorStr forKey:NSLocalizedDescriptionKey];
      *error = [[[NSError alloc] initWithDomain:TASKS_ERROR_DOMAIN code:DUEDATE_VALIDATION_ERROR_CODE userInfo:userInfoDictionary] autorelease];
    }
    return NO;
  }
  return YES;
}

WARNING: code typed in a browser. Caveat Implementor

like image 28
Dave DeLong Avatar answered Nov 15 '22 22:11

Dave DeLong