NSDateComponents on IOS6 not working? - objective-c

I have a simple program which was working with IOS4 and 5.
Now with IOS 6 I'm getting the following error message:
2012-10-05 11:08:16.386 app[1698:19d03] 2012-10-05 09:08:11 +0000
2012-10-05 11:08:18.072 app[1698:19d03] 2012-10-05 09:08:11 +0000
2012-10-05 11:08:19.273 app[1698:19d03] 2012-10-05 09:08:11 +0000
2012-10-05 11:08:19.274 app[1698:19d03] 2012-10-05 09:08:11 +0000
2012-10-05 11:08:19.275 app[1698:19d03] 0
2012-10-05 11:08:25.055 app[1698:19d03] 2011-10-05 09:08:11 +0000
2012-10-05 11:08:25.823 app[1698:19d03] (
"<UILongPressGestureRecognizer: 0xa167f60; state = Possible; view = <UITableViewCellContentView 0xa168000>; target= <(action=_longPressGestureRecognized:, target=<UIPickerTableViewWrapperCell 0xa168090>)>>")
2012-10-05 11:08:25.824 app[1698:19d03] 2012-10-05 09:08:11 +0000
2012-10-05 11:08:25.824 app[1698:19d03] -[__NSArrayI timeIntervalSinceReferenceDate]: unrecognized selector sent to instance 0x94ef5d0
2012-10-05 11:08:25.825 app[1698:19d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI timeIntervalSinceReferenceDate]: unrecognized selector sent to instance 0x94ef5d0'
*** First throw call stack:
(0x1d16012 0x11fae7e 0x1da14bd 0x1d05bbc 0x1d0594e 0x1d25cd3 0xa092 0x120e705 0x145920 0x1458b8 0x206671 0x206bcf 0x205d38 0x17533f 0x175552 0x1533aa 0x144cf8 0x1f4fdf9 0x1f4fad0 0x1c8bbf5 0x1c8b962 0x1cbcbb6 0x1cbbf44 0x1cbbe1b 0x1f4e7e3 0x1f4e668 0x14265c 0x296d 0x28a5)
The first run is with two dates which are equal.
On the second run, I've changed the fhDate on the picker as you can see...
The code is simplified a bit for easier reading:
aiDate = [adoIgazPicker date];
NSLog(#"%#", aiDate);
fhDate = [forgHelyPicker date];
NSLog(#"%#", fhDate);
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *startDate = fhDate;
NSDate *endDate = aiDate;
NSLog(#"%#", startDate);
NSLog(#"%#", endDate);
NSDateComponents *comps = [gregorian components:NSMonthCalendarUnit fromDate:startDate toDate:endDate options:0]; //THIS LINE FAILS IF THE DATES ARE NOT THE SAME
int months = [comps month];
NSLog(#"%i", months);
Thank you for your help!

I've replaced
NSDateComponents *comps = [gregorian components:NSMonthCalendarUnit fromDate:startDate toDate:endDate options:0];
with
NSInteger months = [[[NSCalendar currentCalendar] components: NSMonthCalendarUnit
fromDate: startDate
toDate: endDate
options: 0] month];
and now it's working :).

Related

Getting wrong date while add event in iPhone Reminder app from my application

I am adding an event with NSDate value
“2017-04-25 15:00:00 +0000”
As per my timezone, it’s 2017-04-25 08:40 PM.
I am getting NSDate value from a function.
NSString *strDateTime = #"Tuesday, 25 Apr 2017 08:30 PM";
NSDateFormatter *formatterLocal = [[NSDateFormatter alloc] init];
[formatterLocal setTimeZone:[NSTimeZone systemTimeZone]];
[formatterLocal setDateFormat:#"EEEE, dd MMM yyyy hh:mm a"];
NSDate *dateAdd = [formatterLocal dateFromString:strDateTime];
While I check reminder app it’s showing event with date 25/04/17, 3:00 PM. While it should be 25/04/17, 8:00 PM.
Can anyone please help me out from this!
I have already checked Get wrong time when adding an event to default calendar in iPhone
I just catch my mistake.
I have set the wrong timezone in "dueDateComponents".
Below is my code.
EKReminder *reminder = [EKReminder reminderWithEventStore:self.eventStore];
reminder.dueDateComponents = [self dateComponentsForDefaultDueDate];
- (NSDateComponents *)dateComponentsForDefaultDueDate {
/*
Changing date components
*/
NSCalendar *cal = [NSCalendar currentCalendar];
//[cal setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
NSDateComponents *components = [cal components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitHour | NSCalendarUnitMinute fromDate:[NSDate dateWithTimeIntervalSince1970:[_dictData[#"start"] longLongValue]]];
components.hour = [components hour];
components.minute = [components minute];
return components;
}
I just commented
//[cal setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
Silly mistake :p

Converting different strings to NSDate - 1 is correct, the 2nd is a duplicate of the 1st

For some reason, this code is not converting the second string correctly; this is the code:
NSLog(#"\n\nsearchStartTime: %# searchEndTime: %#",searchStartTime, searchEndTime);
[dateFormatter setDateFormat: #"yyyy-MM-dd HH:mm a"];
startDate = [dateFormatter dateFromString:searchStartTime];
endDate = [dateFormatter dateFromString:searchEndTime];
NSLog(#"\n\nstartDate: %# endDate: %#", startDate, endDate);
This the definition and value of the searchStartTime and searchEndTime:
searchStartTime: 2015-03-05 08:30 AM searchEndTime: 2015-03-05 09:30 AM
This is the result from NSLog:
startDate: 2015-03-05 08:30:00 +0000 endDate: 2015-03-05 08:30:00 +0000
What's wrong with my code here? I want to take these two date/time objects and use them in a NSPredicate to compare dates in a Core Data record.
It all comes down to knowing your format code strings. You are misusing "HH" here so the hour is coming out wrong.
Another problem is that you are not capturing the error. By calling dateFromString:, you are missing out on your chance to hear about errors. Use getObjectValue:forString:range:error: to learn of problems.
Anyway, I substituted "hh" where you have "HH" and the answers came out right:
NSString* searchStartTime = #"2015-03-05 08:30 AM";
NSString* searchEndTime = #"2015-03-05 09:30 AM";
NSLog(#"\n\nsearchStartTime: %# searchEndTime: %#",searchStartTime, searchEndTime);
NSDateFormatter* dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat: #"yyyy-MM-dd hh:mm a"];
NSDate* startDate = [dateFormatter dateFromString:searchStartTime];
NSDate* endDate = [dateFormatter dateFromString:searchEndTime];
NSLog(#"\n\nstartDate: %# endDate: %#", startDate, endDate);
startDate: 2015-03-05 16:30:00 +0000 endDate: 2015-03-05 17:30:00 +0000
I am in California, and the time is shown relative to London, so if you subtract the time difference you'll see that this is correct.
One error is "HH" which is 24-hour tine but you are also using "a" for an & pm.
Instead use "hh" for 12-hour time.
Example:
NSString *searchStartTime = #"2015-03-05 08:30 AM";
NSString *searchEndTime = #"2015-03-05 09:30 AM";
NSLog(#"\n\nsearchStartTime: %# searchEndTime: %#", searchStartTime, searchEndTime);
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat: #"yyyy-MM-dd hh:mm a"];
NSDate *startDate = [dateFormatter dateFromString:searchStartTime];
NSDate *endDate = [dateFormatter dateFromString:searchEndTime];
NSLog(#"\n\nstartDate: %# endDate: %#", startDate, endDate);
Output:
searchStartTime: 2015-03-05 08:30 AM searchEndTime: 2015-03-05 09:30 AM
startDate: 2015-03-05 13:30:00 +0000 endDate: 2015-03-05 14:30:00 +0000
See: ICU Formatting Dates and Times
Also: Date Field SymbolTable.

Compare three dates

I have three dates 'startDate', stopDate and currentDate. I need compare 'startDate' <= 'currentDate' and 'stopDate' >= 'currentDate'. My code.
unsigned int flagsDate = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* fromComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate:startDate];
NSDate* fromDateOnly = [[NSCalendar currentCalendar] dateFromComponents:fromComponents];
NSDateComponents* toComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate:stopDate];
NSDate* toDateOnly = [[NSCalendar currentCalendar] dateFromComponents:toComponents];
NSDate * currentDate = [NSDate date];
NSDateComponents* currComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate: currentDate];
NSDate* currDateOnly = [[NSCalendar currentCalendar] dateFromComponents:currComponents];
NSTimeInterval fromTime = [fromDateOnly timeIntervalSinceReferenceDate];
NSTimeInterval toTime = [toDateOnly timeIntervalSinceReferenceDate];
NSTimeInterval currTime = [currDateOnly timeIntervalSinceReferenceDate];
NSLog(#"%# %#",currentDate, currDateOnly);
NSLog(#"%# %#",startDate, fromDateOnly);
NSLog(#"%# %#",stopDate, toDateOnly);
That's what brings nslog.
2014-04-10 23:59:53.280 Calendar[2148:90b] 2014-04-10 19:59:53 +0000 2014-04-09 20:00:00 +0000
2014-04-10 23:59:53.282 Calendar[2148:90b] 2014-04-10 20:14:12 +0000 2014-04-10 20:00:00 +0000
2014-04-10 23:59:53.282 Calendar[2148:90b] 2015-04-09 20:14:12 +0000 2015-04-09 20:00:00 +0000
How do I compare dates? I need to compare dates only without time. Why change the date if time is less than 20:00?
NSTimeInterval distanceBetweenDates = [StartDate timeIntervalSinceDate:EndDate];
if (distanceBetweenDates > 0) {
NSLog("Greather than ")
} else if (distanceBetweenDates < 0) {
NSLog("less than");
} else {
NSLog("Equal");
}
Alexey, I suggest you incorporate this wonderful NSDate extension in your project: https://github.com/erica/NSDate-Extensions
You can then use
- (NSInteger)distanceInDaysToDate:(NSDate *)anotherDate
And check if it's < 0, 0 or > 0
If you wanted to compare only the dates, do as follows:
NSInteger flagsDate = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);
NSDateComponents* fromComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate:startDate];
NSDateComponents* toComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate:stopDate];
NSDateComponents* currComponents = [[NSCalendar currentCalendar] components:flagsDate fromDate:cu];
NSComparisonResult firstComparison = [[fromComponents date] compare: [currComponents date]];
NSComparisonResult secondComparison = [[toComponents date] compare: [currComponents date]];
then to check your result
if (firstComparison == NSOrderedDescending || firstComparison == NSOrderedSame) {}
if (secondComparison == NSOrderedSame || secondComparison == NSOrderedAscending) {}

dateByAddingTimeInterval argument syntax

If I send the method dateByAddingTimeInterval: to NSDate, like below:
NSDate *today = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0];
NSDate *yesterday = [now dateByAddingTimeInterval:-24.0];
NSArray *dates = [NSArray arrayWithObjects: today, tomorrow, yesterday, nil];
NSLog(#"today's date is %#", [dates objectAtIndex:0]);
NSLog(#"yesterday's date was %#", [dates objectAtIndex:2]);
I get this output:
...The first date is 2012-08-30 02:14:19 +0000
...The third date is 2012-08-30 02:13:55 +0000
Which is strange because the third date should have been 2012-08-29
But... if I change the NSDate messages to:
NSDate *today = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0];
NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0];
Why does adding the * 60.0...
...The first date is 2012-08-30 02:15:25 +0000
...The third date is 2012-08-29 02:15:25 +0000
make the output correct?
Thank you.
NSDate compute time by second.

NSDate results from -(NSDate *)dateFromComponents:(NSDateComponents *)comps

I want to get a NSDate object with NSDateComponents but the hour of the NSDate is 1 hour lower then in the components.
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[cal setLocale:[NSLocale currentLocale]];
[cal setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *hourComp = [[NSDateComponents alloc] init];
hourComp.timeZone = [NSTimeZone localTimeZone];
[hourComp setHour:18];
NSLog(#"%#",hourComp);
NSLog(#"%#",[cal dateFromComponents:hourComp]);
NSLog(#"%#",[NSDate date]);
Console Output:
2012-04-10 19:10:57.505 TestDate[9861:f803] <NSDateComponents: 0x6b6ad30>
TimeZone: Europe/Berlin (CEST) offset 7200 (Daylight)
Hour: 18
2012-04-10 19:10:57.507 TestDate[9861:f803] 0001-01-01 17:06:32 +0000
2012-04-10 19:10:57.508 TestDate[9861:f803] 2012-04-10 17:10:57 +0000
What I want is 18:xx:xx
I note that you're in Europe, and one hour ahead of GMT. When you set the date to 18:xx it thinks you are setting it in Europe, and so it subtracts one hour before storing it in GMT. When you print it out, you're not asking it to be formatted for local time, so it's giving you GMT, which is 17:xx.
You need to use an NSDateFormatter, and set its locale and time zone - just as you did with the NSCalendar object - and then call stringFromDate on it, passing the date you've created.