Getting future date using NSDate and NSTimeInterval - ios

I'm creating a simple timer but am failing to get the resulting date that I'm after.
My problem is that I'm getting -34481.274523 from my NSTimeInterval (nslog at the end) whereas I'm wanting the number of seconds since the current date (currentDate). stopDate is always a date before currentDate.
The code snippet below is called from an nstimer every second. Rather than simply increment an int I'm using a date as it's easier to perform other date related calculations on and format for display.
Here is my code:
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:stopDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
NSString *timeString=[dateFormatter stringFromDate:timerDate];
NSLog(#"nstimeinterval: %f", timeInterval);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components: ( NSHourCalendarUnit | NSYearCalendarUnit) fromDate:timerDate];
NSLog(#"year: %li", (long)components.year);
if (components.year == 2000) {
timeString = #"00:00";
return;
}
NSLog(#"timer: %#", timeString);
timerTicksForCounter = timeString;
NSLog(#"hour: %li", (long)components.hour);
//Used to update uilabel
[self updateTimerLabel];
if (components.year < 2000) {
return;
}
if (components.hour == 0) {
..... I'm doing a bunch of stuff here

Related

How to check the date cross the sunday and rest data

How to check the date cross the Sunday and reset the data?
I need to do reset on every Sunday, if I missed that on Sunday then the reset need to happen if user open the app the following increment date(i.e mon,tue, till saturday).
For Every Sunday or crossed the Sunday one time the reset need to happened, if user forgot to open the application on Rest date.
Following the my code which i try to implemented.
Which was not working as per my requirement, Your feedback is highly appreciated.
-(void) weekDaySundayToRefresh
{
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitWeekOfMonth | NSCalendarUnitWeekday fromDate:now];
NSUInteger weekdayToday = [components weekday];
NSInteger daysToMonday = (8 - weekdayToday) % 7;
nextSunday= [now dateByAddingTimeInterval:60*60*24*daysToSunday];
NSLog(#"nextMonday : %#", nextSunday);
}
-(void) compareDate
{
NSDate *today = [NSDate date]; // it will give you current date
// NSDate *newDate = [MH_USERDEFAULTS objectForKey:#"USER_BACKGROUND_DATE"]; // your date
NSComparisonResult result;
//has three possible values: NSOrderedSame,NSOrderedDescending, NSOrderedAscending
result = [today compare:refreshGoalsDate]; // comparing two dates
if(result==NSOrderedAscending)
{
NSLog(#"today is less");
}
else if(result==NSOrderedDescending)
{
NSLog(#"newDate is less");
NSDate *fromDate;
NSDate *toDate;
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&fromDate
interval:NULL forDate:refreshGoalsDate];
[calendar rangeOfUnit:NSCalendarUnitDay startDate:&toDate
interval:NULL forDate:today];
NSDateComponents *difference = [calendar components:NSCalendarUnitDay
fromDate:fromDate toDate:toDate options:0];
noOfDaysCount = [difference day];
NSLog(#"date difference:%ld",(long)[difference day]);
}
else
NSLog(#"Both dates are same");
}
-(void) checkRefreshGoals:(int)sectionIndex rowIndex:(int)rowIndex
{
NSDateFormatter * formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy-MM-dd"];
NSString * currentDateString = [formatter stringFromDate:[NSDate date]];
NSString * initialNotificationDate = [formatter stringFromDate:refreshDate];
NSDate *currentDate = [formatter dateFromString:currentDateString];
NSDate *refreshDate = [formatter dateFromString:initialNotificationDate];
if ([refreshDate compare:currentDate] == NSOrderedDescending)
{
NSLog(#"date1 is later than date2");
isGoalsRefreshed = NO;
}
else if ([refreshDate compare:currentDate] == NSOrderedAscending)
{
NSLog(#"date1 is earlier than date2");
if (sameDay == YES)
{
isGoalsRefreshed = YES;
[self refreshDataOnSunday:sectionIndex rowIndex:rowIndex];
}
else if (noOfDaysCount > 7)
{
isGoalsRefreshed = YES;
[self refreshDataOnSunday:sectionIndex rowIndex:rowIndex];
}
else
{
isGoalsRefreshed = NO;
}
}
else
{
NSLog(#"dates are the same");
isRefreshed = NO;
}
}
-(void) refreshDataOnSunday:(int)sectionIndex rowIndex:(int)rowIndex
{
if (noOfDaysCount > 7)
{
if (isGoalsRefreshed == YES)
{
// Do rest your data
}
}
else if (sameDay == YES)
{
if (isGoalsRefreshed == YES)
{
// Do reset your data
}
}
else
{
isGoalsRefreshed = NO;
}
}
First you need to save todays date and DayNumber when user opens your app at first time and then you need to compare next app open date so you can estimate either Sunday is gone or not.
/*first check in userDefault for stored Date and Day
Store values in local and check with current date */
NSMutableDictionary *dictStoredData = [USERDEFAULT valueForKey:#"dateTimeDate"];
if (!dictStoredData) {
// user comes first time so store it here
dictStoredData =[[NSMutableDictionary alloc] init];
NSDate *today =[NSDate date];
NSCalendar *gregorian =[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps =[gregorian components:NSCalendarUnitWeekday fromDate:[NSDate date]];
NSInteger weekday = [comps weekday];
int nextSundayVal = 7 - (int)weekday;
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyy-MM-dd"];
NSString *startDate = [format stringFromDate: today];
[dictStoredData setObject:startDate forKey:#"startDate"];
[dictStoredData setObject:[NSString stringWithFormat:#"%d",nextSundayVal] forKey:#"nextSundayVal"];
[USERDEFAULT setObject:dictStoredData forKey:#"dateTimeDate"];
}
else{
NSString *strEndDate = #"2017-01-08";
NSString *strStartDate = [dictStoredData valueForKey:#"startDate"];
int nextSundayVal = (int)[dictStoredData valueForKey:#"nextSundayVal"];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [format dateFromString:strStartDate];
NSDate *endDate = [format dateFromString:strEndDate];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [gregorianCalendar components:NSCalendarUnitDay
fromDate:startDate
toDate:endDate
options:0];
int newDayCount = (int)[components day];
if (newDayCount > nextSundayVal) {
NSLog(#"sunday is gone so reload data!!");
//save this date as a new date and check with this when user come again
}
else {
NSLog(#"sunday is not come yet!!");
}
}
here strEndDate is next date when user opens your application so you can get it from [NSDate date] with same dateformater.
I have run this code in my machine and its printing sunday is gone so reload data so hope this will help you.
As like you we had flow, every friday and more than seven days, its need to update the server.
We did it with following code:
You need to update last updated date.
Check this out:
if ([isFirday isEqualToString:#"Friday"]) {//This is my value from server side (they will give as friay), i think you dont need this condition.
BOOL isSameDay;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMM dd yyyy,HH:mm"];
NSDate *date = [dateFormatter dateFromString:mennuRefreshTime];//Is an last updated date.
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *temp = [dateFormatter stringFromDate:date];
NSDate *lastDate = [dateFormatter dateFromString:temp];
NSString *currentDaystr = [dateFormatter stringFromDate:[NSDate date]];
// Write the date back out using the same format
NSDate *currentDate = [dateFormatter dateFromString:currentDaystr];
if ([lastDate compare:currentDate] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
isSameDay = NO;
} else if ([lastDate compare:currentDate] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
[dateFormatter setDateFormat:#"EEEE"];
NSString *dayName = [dateFormatter stringFromDate:currentDate];
NSString *lastupdateName = [dateFormatter stringFromDate:lastDate];
if ([dayName isEqualToString:lastupdateName]) {
isSameDay = YES;
}else{
isSameDay = NO;
}
} else {
NSLog(#"dates are the same");
isSameDay = YES;
}
if (isSameDay == YES) {
return;
}
NSCalendar *calender =[[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calender components:NSCalendarUnitDay fromDate:lastDate toDate:currentDate options:0];
int day = (int)[components day];
if (day >= 7) {
[self getTopList];
}else{
[dateFormatter setDateFormat:#"EEEE"];
NSString *dayName = [dateFormatter stringFromDate:currentDate];
if ([dayName isEqualToString:isFirday]) {
[self getTopList];
}else{
return;
}
}
}

Get days between days

Before giving downvote, comment the reason
I have created a UIDatePicker with minimum & maximum date values (i.e. 6 months of date picker) Now, i need to get 7 days from selected date. There i need to check the conditions,
If date is today date i need to get 7 days from today onwards
If date is last date (i.e. last date of picker) need to get last 7 days including last day
If date is middle of today's date & last date i need to get last 3 days, next 3 days including today date. And, also while getting last & next 3 days it shouldn't get exceed with picker's date limit.
Here's my code snippet:
- (void)addDays:(NSInteger)range {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MM-yyyy"];
NSDate *startDate = self.selectedDate;
for (int x = 0; x <= range; x++) {
NSLog(#"%#", [dateFormat stringFromDate:startDate]);
startDate = [startDate dateByAddingTimeInterval:(60 * 60 * 24)];
}
}
- (void)minusDays:(NSInteger)range {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MM-yyyy"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [NSDateComponents new];
for (NSInteger i=0; i<range; i++) {
comps.day += -1;
NSDate *date = [calendar dateByAddingComponents:comps toDate:self.selectedDate options:0];
NSDateComponents *components = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:date];
NSLog(#"%#", [dateFormat stringFromDate:[calendar dateFromComponents:components]]);
}
}
- (void)calculateDateRange {
if ([dateArray count] > 0) {
[dateArray removeAllObjects];
}
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *lastcomponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
lastcomponents.month += 6;
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy/MM/dd"];
NSDate *currentDate = [NSDate date];
NSDate *selectedD = self.selectedDate;
NSDate *endDate = [calendar dateFromComponents:lastcomponents];
NSDate *fromDate;
NSDate *toDate;
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:currentDate];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:selectedD];
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
NSInteger first = [difference day];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:selectedD];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:endDate];
NSDateComponents *difference2 = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
NSInteger second = [difference2 day];
if ((first == 0 || first < 3) && second > 7) {
[self addDays:7];
} else if (first >= 3 && second > 7) {
[self minusDays:3];
[self addDays:3];
}else if (second == 7 || second < 7) {
[self minusDays:7];
}
}
This is working fine. But, can't get exact last & previous days.
Anyone has idea on this?
My interpretation of your needs
You have a date picker. When a date is picked you need to create a 7 day range around that selected date.
So, if the selected date is 15/11/2014 then you want 3 days either side so...
12/11/2014 - 18/11/2014.
However, the date range cannot exceed the limits of the date picker. So if the minimum date on the date picker is set to 14/11/2014 then (in the above example) the date range would be...
14/11/2014 - 21/11/2014
Even after your additional explanation this is still my interpretation. And my code does exactly this.
Solution
You CANNOT use 60*60*24 to mean one day. This is just wrong. When dealing with dates you should always be using NSDateComponents and NSCalendar.
Also, break down your problem into small steps. There is no reason to do everything in one giant function.
OK I guess you have a datePicker action somewhere so I'd code it like this...
- (void)datePickerDateChanged
{
NSDate *minimumDate = self.datePicker.minimumDate;
NSDate *maximumDate = self.datePicker.maximumDate;
NSDate *selectedDate = self.datePicker.date;
NSDate *startDate;
NSDate *endDate;
if ([self numberOfDaysFromDate:minimumDate toDate:selectedDate] < 3) {
// get 7 days after minimumDate
startDate = minimumDate;
endDate = [self dateByAddingDays:6 toDate:minimumDate];
} else if ([self numberOfDaysFromDate:selectedDate toDate:maximumDate] < 3) {
// get 7 days before maximumDate
startDate = [self dateByAddingDays:-6 toDate:maximumDate];
endDate = maximumDate;
} else {
// get 3 days before and 3 days after selectedDate
startDate = [self dateByAddingDays:-3 toDate:selectedDate];
endDate = [self dateByAddingDays:3 toDate:selectedDate];
}
// Here startDate and endDate define your date range.
}
- (NSDate *)dateByAddingDays:(NSInteger)days toDate:(NSDate *)date
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.day = days;
return [calendar dateByAddingComponents:components toDate:date options:0];
}
- (NSInteger)numberOfDaysFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
// always return positive. We just want magnitude of days.
return components.day > 0 ? components.day : -components.day;
}
This is untested and just a first attempt.

Open Hours in Objective-C - Time between two times NSDate

I am trying to perform a segue in Objective-C (XCode) for iOS devices, when the time right now is between two other fixed times. Just like "Open Hours" for stores - when the time right now is between open and close hour.
Here is the code I have been working on - some of the code may look familiar, because I found some useful stuff on SO which helped me - but still I can't get it to work. It doesn't perform the segue when the time passes startTime. It should be in the specified time interval.
The time is in 24-hour format.
// set start time and end time
NSString *startTimeString = #"23:00";
NSString *endTimeString = #"05:00";
// set date formatter 24-hour format
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"HH:mm"];
// german timezone
NSLocale *locale = [[NSLocale alloc]initWithLocaleIdentifier:#"de_DE"];
NSString *nowTimeString = [formatter stringFromDate:[NSDate date]];
// set NSDates for startTime, endTime and nowTime
NSDate *startTime = [formatter dateFromString:startTimeString];
NSDate *endTime = [formatter dateFromString:endTimeString];
NSDate *nowTime = [formatter dateFromString:nowTimeString];
[formatter setLocale:locale];
// compare endTime and startTime with nowTime
NSComparisonResult result1 = [nowTime compare:endTime];
NSComparisonResult result2 = [nowTime compare:startTime];
if ((result1 == NSOrderedDescending) &&
(result2 == NSOrderedAscending)){
NSLog(#"Time is between");
[self performSegueWithIdentifier:#"openHours" sender:self];
} else {
NSLog(#"Time is not between");
}
thanks for taking your time to look at my question. I have been searching and searching, trying and trying, but no luck in making it work yet. Hopefully your answers will help me.
You should little bit change you code
// set NSDates for startTime, endTime and nowTime
int startTime = [self minutesSinceMidnight:[formatter dateFromString:startTimeString]];
int endTime = [self minutesSinceMidnight:[formatter dateFromString:endTimeString]];
int nowTime = [self minutesSinceMidnight:[formatter dateFromString:nowTimeString]];;
[formatter setLocale:locale];
if (nowTime < endTime && nowTime > startTime) {
NSLog(#"Time is between");
} else if (nowTime > endTime && nowTime < startTime) {
NSLog(#"Time is between");
} else {
NSLog(#"Time is not between");
}
And implement method for calculating time:
-(int) minutesSinceMidnight:(NSDate *)date
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
unsigned unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags fromDate:date];
return 60 * [components hour] + [components minute];
}
I am interested in an answer that works on ANY date, and not fixed dates for opening and closing.
In that case the simplest approach would be using NSDateComponents. You could store hour, minutes and maybe weekday for opening and closing. to check for now you would break up [NSDate now] into the same NSDateComponents and cop are those.

Get time from pressed button (hold pressed)

When trying to get the time, I am not getting the expected value.
When I ran this, the time was 19:59. And in the timeDifferenceString, the Value was 71976.894206.
I think that this is the current time.
I calculate 71976 / 3600 = 19,99 h
0,99 * 60 = 59,4 m
0,4 * 60 = 24 s
So I get the time 19:59:24 o'clock. But I want get the difference between the first time and the second time and not the current time in seconds.
I want only get the time when I (hold) pressed the button
and the time that the button is not pressed (by starting the first time if I press on the button and stopped if I press on an other button).
- (IBAction)pressTheButton:(id)sender {
NSDate * now = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss:SSS"];
NSString *currentTime = [formatter stringFromDate:now];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components; //= [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
[components setHour:10];
NSDate* firstDate = [NSDate date];
NSString *getTime = [formatter stringFromDate:now];
getTime = [formatter stringFromDate:firstDate];
if (iX==0)
{
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
firstDate = [calendar dateFromComponents:components];
getTime = [formatter stringFromDate:firstDate];
//firstDate = [NSDate date];//[dateFormatter dateFromString:#"00:01:00:090"];
}
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
//NSDate* secondDate = [dateFormatter dateFromString:#"10:01:02:007"];
NSDate * secondDate = [calendar dateFromComponents:components];
getTime = [formatter stringFromDate:firstDate];
NSTimeInterval timeDifference = [firstDate timeIntervalSinceDate:secondDate];
NSString *timeDifferenceString = [NSString stringWithFormat:#"%f", timeDifference];
timeDiff[iX] = [timeDifferenceString intValue];
[timeLabel setText:timeDifferenceString];
iX++;
}
If you have a better solution for my problem pleas help me.
Look at UIControlEventTouchDown, UIControlEventTouchUpInside here: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIControl_Class/Reference/Reference.html
Then I suppose you want to store an NSDate of when you pressed down in some sort of ivar or property (UIControlEventTouchDown) and another one when you release the button (UIControlEventTouchUpInside or UIControlEventTouchUpOutside) and then call -timeIntervalSinceDate: on that date. So it would look roughly like this:
- (IBAction)pressedDown:(id)sender {
self.pressedDownDate = [NSDate date];
}
- (IBAction)touchedUp:(id)sender {
NSDate *now = [NSDate date];
NSLog(#"Time passed: %d", [now timeIntervalSinceDate:self.pressedDownDate]);
}

Showing "past" and "upcoming" sections UITableView with FetchedResultsController

I'm having a bit of difficulty grouping my table view by past and upcoming. This would be determined by a date field in my Core Data model. So all items with a date > today would be upcoming, and all with a date < today would be considered past. Any insight into this would be greatly appreciated.
You can use this function in your entities class:
-(NSString*)dateToStringForSectionTitels{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSString *formattedDateString;
[dateFormatter locale];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:self.startDate];
NSDate *otherDate = [cal dateFromComponents:components];
if([today isEqualToDate:otherDate]) {
formattedDateString = #"Today";
}else{
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
formattedDateString = [dateFormatter stringFromDate:self.startDate];
}
NSTimeInterval distanceBetweenDates = [self.startDate timeIntervalSinceDate:[NSDate date]];
double secondsInAnMinute = 60;
NSInteger minutsBetweenDates = distanceBetweenDates / secondsInAnMinute;
if (minutsBetweenDates<30) {
formattedDateString = #"Starting Soon";
}else if(minutsBetweenDates<0){
formattedDateString = #"In the past";
}
return formattedDateString;
}
It will return
The date in a string if the event is in the future
"Today" if the event is today.
"Starting soon" if the event is starting in 30 minutes - (You can range it to what ever you wish.
"In the past" if the event is in the past.
Then just pass the "dateToStringForSectionTitels" to your fetch result controller.
Good luck.

Resources