I've tried all the time calculating examples I found on this site but somehow I'm getting 0 as value every time. I'm new to IOS and the NSDate is giving me a run for it's money :)
I want to record time A when I press button "startStop", and then record time B when I press it again. Pressing it a second time (deselecting) has to calculate the time elapsed between these 2 dates. So far I have this:
-(IBAction)buttonClick {
NSDate *startStopDate = [NSDate alloc];
NSDateFormatter *formatter= [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
NSString *currentTime = [[NSString alloc] init];
NSString *currentTime2 = [[NSString alloc]init];
NSDate *start =[ [NSDate alloc]init];
NSDate *stop = [[NSDate alloc] init];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
if (startStop.selected==NO) {
NSLog(#"started");
[startStop setSelected:YES];
startStopDate = [NSDate date];
currentTime = [formatter stringFromDate:startStopDate];
NSLog(#"Current timestarted is %#",currentTime);
startTime.text = currentTime;
start = [formatter dateFromString:currentTime];
}
else {
NSLog(#"Selected");
[startStop setSelected:NO];
startStopDate = [NSDate date];
currentTime2 = [formatter stringFromDate:startStopDate];
NSLog(#"Current time is %#",currentTime2);
stopTime.text = currentTime2;
stop = [formatter dateFromString:currentTime2];
NSUInteger unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [gregorianCalendar components:unitFlags
fromDate:start
toDate:stop
options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds = [components second];
NSLog(#"hello %d, %d, %d", hours, minutes, seconds);
}
}
My labels give the correct hour:minute output when pressed, but I can't seem to get them to transfer to the date calculation.
I've been trying numerous variations with dateFromString and stringFromDate and multiple date/string objects as you can see, but so far I only get big negative numbers or just zero as result. Any help appreciated ;)
Greets, Nick
That's because start is a local variable. When the button is clicked the second time, your code will skip the if block and go straight to the else block, leaving the start variable allocated but not initialized to anything useful. You need to store this start value outside of a local context if you want to use it to calculate the difference between the start and stop times.
Related
Here's my code:
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSString *currentTime = [dateFormatter stringFromDate:currDate];
NSDate *now = [NSDate date];
int interval = 1*60; // one minute (minutes*60)
long int nowSeconds = (long int) [now timeIntervalSince1970];
int secondsLeft = interval - (nowSeconds % interval);
NSDate *nextIntervalDate = [NSDate dateWithTimeIntervalSince1970:nowSeconds+secondsLeft];
NSString *nextTrigger = [dateFormatter stringFromDate:nextIntervalDate];
timeRemaining.text = [NSString stringWithFormat:#"%02d:%02d", secondsLeft/60, secondsLeft%60];
NSLog([NSString stringWithFormat:#"%#:%#", currentTime, nextTrigger]);
if ([currentTime isEqualToString:nextTrigger]) {
}
Problem is, 'if ([currentTime isEqualToString:nextTrigger])' is never equal. Because nextTrigger changes to the next time segment before they're equal. Here is the NSLog:
2013-01-17 15:54:59.987 app[35987:c07] 15:54:59:15:55:00
2013-01-17 15:54:59.997 app[35987:c07] 15:54:59:15:55:00
2013-01-17 15:55:00.007 app[35987:c07] 15:55:00:15:56:00 <----RIGHT HERE
2013-01-17 15:55:00.016 app[35987:c07] 15:55:00:15:56:00
My code's nextTrigger is basically a round up of the current time by the nearest minute. ALSO, this whole code segment is in a repeating NSTimer every .1 seconds.
How can I fix this?
If you have code that you'd like triggered when the next whole minute passes, it's inefficient to repeatedly check to see if said time has passed. Put that code in its own method, and create a single NSTimer to trigger it at the appropriate time.
NSDate* date = [NSDate date] ;
NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDateComponents* secondsComponents = [calendar components:NSSecondCalendarUnit fromDate:date] ;
NSTimeInterval secondsUntilNextWholeMinute = 60 - secondsComponents.second ;
[NSTimer scheduledTimerWithTimeInterval:secondsUntilNextWholeMinute target:self selector:#selector(yourMethod) userInfo:nil repeats:NO ] ;
I had a somewhat similar problem. What I did was make a copy and check it by that.(one thing is to have both oldTrigger and newTrigger declared already)Check this code
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSString *currentTime = [dateFormatter stringFromDate:currDate];
NSDate *now = [NSDate date];
int interval = 1*60; // one minute (minutes*60)
long int nowSeconds = (long int) [now timeIntervalSince1970];
int secondsLeft = interval - (nowSeconds % interval);
NSDate *nextIntervalDate = [NSDate dateWithTimeIntervalSince1970:nowSeconds+secondsLeft];
oldTrigger = nextTrigger;
nextTrigger = [dateFormatter stringFromDate:nextIntervalDate];
timeRemaining.text = [NSString stringWithFormat:#"%02d:%02d", secondsLeft/60, secondsLeft%60];
NSLog([NSString stringWithFormat:#"%#:%#", currentTime, nextTrigger]);
if ([currentTime isEqualToString:oldTrigger]) {
}
In My application I have to complete a particular task in given time.So first i calculated the time complete the task in seconds and then add that time to the current that like this.
NSDate *mydate = [NSDate date];
NSTimeInterval TotalDuraionInSec = sec.cal_time * 60;
TaskCmpltTime = [mydate addTimeInterval:TotalDuraionInSec];
NSLog(#"task will be completed at%#",TaskCmpltTime);
now I compare time like this
if([CurrentTime isEqualToDate:AfterCmpltTime]){
NSLog (#"Time Finish");
}
but I want to know is Time is left or not.Is current time is less then or greater then current time how can i know this ?
timeIntervalSinceNow compares the NSDate with Now. if NSDate is after Now the return value is possitive, if the date is earlier than Now the result is negative.
double timeLeft = [TaskCompltTime timeIntervalSinceNow];
if( timeLeft > 0.0 )
// still time left
else
//time is up
I have an example where I get the time from a picker and check if its today or tomorrow. You should be able to just take the code and use it in your way...
int selectedHour = [customPickerView selectedRowInComponent:0];
int selectedMinute = [customPickerView selectedRowInComponent:1];
NSDate *today = [NSDate date];
NSDateFormatter *weekdayFormatter = [[[NSDateFormatter alloc] init]autorelease];
NSDateFormatter *hmformatter = [[[NSDateFormatter alloc] init]autorelease];
[hmformatter setDateFormat: #"hh mm"];
[weekdayFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[weekdayFormatter setDateFormat: #"EE"];
// NSString *formattedDate = [formatter stringFromDate: today];
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]autorelease];
NSDateComponents *dateComponentsToday = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit) fromDate:today];
NSInteger currentHour = [dateComponentsToday hour];
NSInteger currentMinute = [dateComponentsToday minute];
NSString *weekday;
if ((selectedHour > currentHour) | ((selectedHour == currentHour) & (selectedMinute > currentMinute))) {
//so we are still in today
weekday = [weekdayFormatter stringFromDate: today];
weekday = NSLocalizedString(#"today", #"today");
} else {
//the timer should start tomorrow
NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *tomorrow = [today dateByAddingTimeInterval:secondsPerDay];
weekday = [weekdayFormatter stringFromDate: tomorrow];
weekday = NSLocalizedString(#"tomorrow", #"tomorrow");
}
Yeah, for your purposes it's probably best to work in time intervals. The NSTimeInterval in Objective-C is an alias for double, and it represents a time value in seconds (and, of course, fractions, down to at least millisecond resolution).
There are several methods on NSDate for this -- +timeIntervalSinceReferenceDate, which returns the number of seconds since Jan 1, 2001, -timeIntervalSinceReferenceDate, which returns the difference in time between the supplied NSDate object and Jan 1, 2001, -timeIntervalSinceDate:, which returns the difference in seconds between the two NSDate objects, and -timeIntervalSinceNow, which returns the difference between the current time and the NSDate object.
Lots of times it's most convenient to store an NSDate value as an NSTimeInterval instead (eg, timeIntervalSinceReferenceDate). This way it doesn't have to be retained and disposed, etc.
I have two time.. one fetched directly as string(#"21:00") and other is the current time. I want to display a count down timer showing how much time left from now to reach 21:00.
For eg: the label i use should display "You have 3hrs and 30 minutes left.." if the current time is 17:30.
thanks..
OK have completely revised my answer, and have created a complete solution to the problem, with fully tested sample code available on github.
Enjoy :)
Something like this should do it. This will give you the remaining time in seconds. Then you just need to to standard timer stuff as indicated in other answers.
//assumption: targetTime is after now
NSString *targetTime = #"21:00";
//split our time into components
NSArray *timeSplit = [targetTime componentsSeparatedByString:#":"];
NSUInteger hours = [[timeSplit objectAtIndex:0] intValue];
NSUInteger minutes = [[timeSplit objectAtIndex:1] intValue];
NSDate *now = [NSDate date];
//split now into year month day components
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [currentCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:now];
//set our time components from above
[dateComponents setHour:hours];
[dateComponents setMinute:minutes];
NSDate *targetDate = [currentCalendar dateFromComponents:dateComponents];
//ensure target is after now
if ([targetDate timeIntervalSinceDate:now] < 0)
{
NSDateComponents *day = [[NSDateComponents alloc] init];
[day setDay:1];
targetDate = [currentCalendar dateByAddingComponents:day toDate:targetDate options:0];
}
NSTimeInterval timeRemaining = [targetDate timeIntervalSinceDate:now];
You create a NSTimer that fires every second:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(tickClock) userInfo:nil repeats:YES];
When it fires, you enter a method:
- (void)tickClock;
in there, you compare the date you have against the current date [NSData currentDate];
Like
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:yourDate];
where distanceBetweenDates is specified in seconds.
To create a date from your string create a NSDate accordingly
NSInteger year = 2011;
NSInteger month = 8;
NSInteger day = 26;
NSInteger hour = 21;
NSInteger minute = 0;
NSInteger second = 0;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:year];
[components setMonth:month];
[components setDay:day];
[components setHour:hour];
[components setMinute:minute];
[components setSecond:second];
NSDate *date = [calendar dateFromComponents:components];
[components release];
In my application I'm using following codes to retrieve current date and day :-
NSDate *today1 = [NSDate date]; NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:#"dd/MM/yyyy :EEEE"]; NSString *dateString11 = [dateFormat stringFromDate:today1];
NSLog(#"date: %#", dateString11);
//[dateFormat release];
NSCalendar *gregorian11 = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components1 = [gregorian11 components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today1];
[components1 setDay:([components1 day]-([components1 weekday]-1))];
NSDate *beginningOfWeek1 = [gregorian11 dateFromComponents:components1];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:#"dd/MM/yyyy :EEEE"];
NSString *dateString_first = [dateFormat_first stringFromDate:beginningOfWeek1];
NSLog(#"First_date: %#", dateString_first);
[components1 setDay:([components1 day]-([components1 weekday]-1) + 6)]; now =[gregorian dateFromComponents:components1]; [format setDateFormat:#"dd/MM/yyyy :EEEE"]; dateString = [format stringFromDate:now]; NSLog(#" week Last_date: %#", dateString);
but using above code I only got the current day and Date and first day of week but I need to get last day of week. But it gives the wrong output. Where am I wrong in my code and what modification is needed to get last day/date of week?
When you call setDay: you are sometimes setting it to a negative day. I don't know if setDay and/or dateFromComponents: will handle that.
To create a NSDate for a date/time that is in the past (or future) you can subtract (or add) the number of seconds that you want to go back (or forward), like this:
// convert to seconds
NSTimeInterval tmpSecs = [[NSDate date] timeIntervalSinceReferenceDate];
// Shift the date/time (in seconds) to a new date X days away:
tmpSecs += daysOffset * 86400; // 86400 seconds per day
// convert back to NSDate and return the result
return [NSDate dateWithTimeIntervalSinceReferenceDate:tmpSecs];
I'm looking to get the current hour and minute on a user's iPhone for display in an app that doesn't show the status bar. Is there a simple way to do this?
// get current date/time
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
NSString *currentTime = [dateFormatter stringFromDate:today];
[dateFormatter release];
NSLog(#"User's current time in their preference format:%#",currentTime);
-(void)currentTime
{
//Get current time
NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *dateComponents = [gregorian components:(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:now];
NSInteger hour = [dateComponents hour];
NSString *am_OR_pm=#"AM";
if (hour>12)
{
hour=hour%12;
am_OR_pm = #"PM";
}
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];
[gregorian release];
NSLog(#"Current Time %#",[NSString stringWithFormat:#"%02ld:%02ld:%02ld %#", (long)hour, (long)minute, (long)second,am_OR_pm]);
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter stringFromDate:[NSDate date]]
[dateFormatter release]; dateFormatter = nil;
I think you should try this. The timeZone is important.
See this similar question for an answer. You will have to change it to your date format.
[[NSDate date] timeIntervalSince1970];
if you are looking to calculate time intervals, you are better off using CACurrentMediaTime
double currentTime = CACurrentMediaTime();
A shorter approach
NSDate * now = [NSDate date];
timeLabel.text = [NSDateFormatter localizedStringFromDate:now
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterShortStyle];
CFAbsoluteTimeGetCurrent()
Absolute time is measured in seconds relative to the absolute reference date of Jan 1 2001 00:00:00 GMT. A positive value represents a date after the reference date, a negative value represents a date before it. For example, the absolute time -32940326 is equivalent to December 16th, 1999 at 17:54:34. Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.