views:

593

answers:

2

This is probably a silly question but I can't seem to find an answer.

I am using a date picker to allow a user to enter a date and it is also setting the time to the current time (I init the picker with [NSDate date]).

Is there a way to change the time component of the date? I am later calculating time intervals which returns seconds and I am getting some odd behavior because of the time.

This code shows the date entry:

@implementation AddEventViewController
@synthesize backgroundColor, nameField, dateField, datePicker, eventName, eventDate;

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.view.backgroundColor = self.backgroundColor; 
}

- (void)viewDidLoad 
{
    [super viewDidLoad];
    dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; 
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];


    CGSize size = self.view.bounds.size;
    CGRect frame = CGRectMake(0, size.height - 216, 320, 216);
    datePicker = [[UIDatePicker alloc] initWithFrame: frame];
    datePicker.datePickerMode = UIDatePickerModeDate;
    datePicker.hidden = YES;
    datePicker.date = [NSDate date];
    [datePicker addTarget:self
                   action:@selector(changeDateInLabel:)
         forControlEvents:UIControlEventValueChanged];

    [self.view addSubview: datePicker];
}
- (void)didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning];
}

-(IBAction)doneButton
{
    if ((nameField.text != nil))
    {
     self.eventName = nameField.text;
     self.eventDate = datePicker.date;
     [[NSNotificationCenter defaultCenter]postNotificationName:@"EventAddDone" object:nil];
    }
    else
    {
     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Enter Event Name" message:nil delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil];
     [alertView show];
     [alertView release];
    } 
}

-(IBAction)cancelButton
{
    [[NSNotificationCenter defaultCenter]postNotificationName:@"EventAddCancel" object:nil];

}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

- (void)changeDateInLabel:(id)sender
{
    dateField.text = [dateFormatter stringFromDate:[datePicker date]];
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
{
    if(textField == dateField)
    {
     dateField.placeholder = @" ";
     dateField.text = [dateFormatter stringFromDate:[datePicker date]];
     datePicker.hidden = NO; 
     [nameField resignFirstResponder];
     return NO;
    }
    return YES;
}

- (void)dealloc 
{
    self.backgroundColor = nil;
    self.nameField = nil;
    self.dateField = nil;
    self.datePicker = nil;
    self.eventName = nil;
    self.eventDate = nil;
    [dateFormatter release];
    [super dealloc];
}
@end

My use of the recorded date is similar to the following:

NSTimeInterval age = [enteredDate timeIntervalSinceNow];
//do some math on the age variable to get number of days since the event occurred.
+2  A: 
NSInteger days = [[[NSCalendar currentCalendar] components:NSDayCalendarUnit
                                                  fromDate:enteredDate
                                                    toDate:[NSDate date]
                                                   options:0] day];
jtbandes
Very nice, thank you. I did have to change NSInterval to NSTimeInterval but it worked after that.
Eric
Oops, sorry, I meant NSInteger. NSDateComponents (which is what's created using `components:fromDate:toDate:options:` stores components as NSIntegers.
jtbandes
Actually now my code looks much better but I am still having an issue. Here is a log entry that explains what I mean:from 2009-11-19 21:06:40 -0500 to 2009-11-18 21:14:56 -0500 is 0 daysI would like that to ignore the time and consider that one day apart. Any ideas?
Eric
The best thing I can think of for that situation, if it doesn't work right now, is use `components:fromDate:` for both `enteredDate` and the current date, then compare the days manually.
jtbandes
+2  A: 

Two options:

Option 1:

int fromDate = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit
                                                       inUnit:NSEraCalendarUnit
                                                      forDate:enteredDate];
int toDate =  [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit
                                                      inUnit:NSEraCalendarUnit
                                                     forDate:[NSDate date]];
int days = toDate - fromDate;

option 2:

NSDate *dateA, *dateB;
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
                                startDate:&dateA
                                 interval:NULL
                                  forDate:enteredDate];

[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
                                startDate:&dateB
                                 interval:NULL
                                  forDate:[NSDate date]];
//From here, apply the above method using components:fromDate:toDate:
//with dateA and dateB, which are set to the beginning of the days on
//which they lie.
Ed Marty
I used option 2 and it worked perfectly. Thanks!
Eric
One thing to make sure you test is if the two dates lie on opposite sides of either daylight savings time boundary, does it still return the same value. I've had to deal with that issue on several occasions.
Ed Marty