Issue in finding time difference - ios

In my app, I want to know the difference between:
the total hours worked in the week(54.30 hours)
and
the total hours worked on a specific day(10.45 hours)
For example, I want to know the value of (54.30 hours - 10.45 hours) in
hours. Since the total hours of week is greater than 24 hrs, I
couldn't convert it into NSDate.

Use this 2 functions,this will help you
The below function will return total seconds from the hour string
- (NSNumber *)secondsForTimeString:(NSString *)string {
NSArray *components = [string componentsSeparatedByString:#"."];
NSInteger hours = [[components objectAtIndex:0] integerValue];
NSInteger minutes = [[components objectAtIndex:1] integerValue];
//NSInteger seconds = [[components objectAtIndex:2] integerValue];
return [NSNumber numberWithInteger:(hours * 60 * 60) + (minutes * 60)];
}
And below function will return formatted time from seconds
- (NSString *)timeFormatted:(int)totalSeconds {
//int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return [NSString stringWithFormat:#"%02d.%02d",hours, minutes];
}
Now you can calculate the remaining hours like this :
int diffrence =[[self secondsForTimeString:#"54.30"] intValue] - [[self secondsForTimeString:#"10.45"] intValue];
NSLog(#"Remaining Hours - %#",[self timeFormatted:diffrence]);

Related

running timers in tableViewCells being overwritten when tableView scrolls

I have tried asking this question several times but I haven't been able to explain what is going on. Maybe some screen shots may help. I can only post one because I don't have enough reputation points yet.
screenshot after tableview scroll
You can see that one of the timers (2) has been reset. I have tried to fix this multiple ways without success. Here is the code that puts the timers into the tableview cells:
-(void) calculateTimer:(NSTimer *)theTimer
{
self.timerItem = [theTimer userInfo];
// for date only cell
if(self.timerItem.timerType == 0){
[theTimer invalidate];
}
for (NRCItemCell *cell in [self.tableView visibleCells])
{
NSIndexPath *ip = [self.tableView indexPathForCell:cell];
NSUInteger row = [[[NRCItemStore sharedStore]allItems] indexOfObjectIdenticalTo:self.timerItem];
if (row == ip.row){
[self configureTimers:cell forRowAtIndexPath:ip];
cell.timer.text = self.timerItem.timerOutput;
cell.timerName.text = self.timerItem.timerName;
}
}
}
-(void)configureTimers:(NRCItemCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NRCtimerItem *item = [[NRCItemStore sharedStore]allItems][indexPath.row];
NSInteger timerType = item.timerType;
// timerType set by TimerTypeTableView Controller as follows:
// 0 - date
// 1 - seconds elapsed
// 2 - minutes elapsed
// 3 - hours elapsed
// 4 - days elapsed
// 5 - months elapsed
// 6 - years elapsed
switch (timerType) {
case 0:{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
NSDate *date = [NSDate date];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
item.timerOutput = formattedDateString;
}
break;
case 1:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = round(interval);
div_t h = div(time, 3600); //seconds total, divided by 3600 equals
int hours = h.quot; // hours, divided by 60 equals
div_t m = div(h.rem, 60); // minutes
int minutes = m.quot;
int seconds = m.rem; // and remainder is seconds
// NSLog(#"%d:%d:%d", hours, minutes, seconds);
//NSString *intervalString = [NSString stringWithFormat:#"%ld", (long)time];
NSString *intervalString = [NSString stringWithFormat:#"%d hours, %d minutes, %d seconds", hours, minutes, seconds];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
case 2:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = roundf(interval);
div_t h = div(time, 3600); // seconds total, divided by 3600 equals
int hours = h.quot; // hours, divided by 60 equals
div_t m = div(h.rem, 60); // minutes
int minutes = m.quot;
NSString *intervalString = [NSString stringWithFormat:#"%d hours, %d minutes", hours, minutes];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
case 3:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = roundf(interval);
div_t h = div(time, 3600); // seconds total, divided by 3600 equals
int hours = h.quot; // hours
NSString *intervalString = [NSString stringWithFormat:#"%d hours", hours];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
case 4:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = roundf(interval);
div_t h = div(time, 3600); // seconds total, divided by 3600 equals
int hours = h.quot; // hours, divided by 24 equals
div_t d =div(h.rem, 24); // days
int days = d.quot;
NSString *intervalString = [NSString stringWithFormat:#"%d days, %d hours", days, hours];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
case 5:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = roundf(interval);
div_t h = div(time, 3600); // seconds total, divided by 3600 equals
__unused int hours = h.quot; // hours, divided by 24 equals
div_t d =div(h.rem, 24); // days
int days = d.quot;
div_t y = div(d.rem, 12);// divided by 12 equals months
int months = y.quot;
NSString *intervalString = [NSString stringWithFormat:#"%d months, %d days", months, days];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
case 6:
{
NSTimeInterval interval = [self.timerItem.startTime timeIntervalSinceNow];
interval = (-1 * interval);
int time = roundf(interval);
div_t h = div(time, 3600); // seconds total, divided by 3600 equals
__unused int hours = h.quot; // hours, divided by 24 equals
div_t d =div(h.rem, 24); // days
int days = d.quot;
div_t y = div(d.rem, 365);// divided by 365 equals years
int years = y.quot;
NSString *intervalString = [NSString stringWithFormat:#"%d years, %d days", years, days];
NSString *outputString = [intervalString stringByAppendingString:#" ago"];
item.timerOutput = outputString;
}
break;
}
}
The key is the for(NRCItemCell *cell in [self.tableView visibleCells]) fast enumeration. The idea is to loop through the visible cells and only update a cell if the cell's indexPath is equal to the position of the timer in my datastore. However, it looks like scrolling the tableView causes a mismatch between indexPath and and position of the timer in the datastore so that the wrong cell gets overwritten. I have searched all over for an answer and have tried several different approaches but the solution depends on the subtitle label in my custom cell not being overwritten unless the cell position matches the datastore position (which is the way MVC should work, as I understand it). But using reusable cells and scrolling apparently doesn't work the way I thought it did. If there is a solution, I sure would like the help. Thanks in advance!
Your main issue here is the reuse of the cells. Every time you scroll the table the cells are reused with the data of other cells. To keep it short, store your timers data in an array and not in the actual cell.
Importent pointers:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
cell.timerView.data = nil; //reset the data in the current timer
myCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)// Makes sure the cell is still visible
updateCell.timerView.data = timersArray[indexpath.row];
});
}
My bad. I found the bug in my code. It wasn't with tableView at all. I was storing the timers in an array, correctly, not in the cell, even though that's what the comments in the code said. The bug was that I was inadvertently firing a timer every pass through the tableView, so these timers would fire at unpredictable times and then my code would overlay the cell for the corresponding timer. A lot of debugging work, but good experience. Code is working now.
Thanks for the comments!

iOS display time as score and highscore on a UILabel

I'm having a problem when I'm trying to display the score as a highscore.
This is my code for getting the time ont the label on the correct format.
- (void)populateLabelwithTime:(int)milliseconds {
int seconds = milliseconds / 1000;
int minutes = seconds / 60;
int hours = minutes / 60;
seconds -= minutes * 60;
minutes -= hours * 60;
resultScoreLabel.text = [NSString stringWithFormat:#"%ds:%dms",seconds, milliseconds%1000];
if (currentTime > highScore) {
[[NSUserDefaults standardUserDefaults] setInteger:currentTime forKey:#"highscore"];
resultHighScoreLabel.text = [NSString stringWithFormat:#"%i",highScore +10];
}
else {
}
}
-(void)scoring {
currentTime += 10;
[self populateLabelwithTime:currentTime];
highScore = [[NSUserDefaults standardUserDefaults] integerForKey:#"highscore"];
}
The score format appears correct.
score is: 1s:186ms
but the highscore appears wrong
Your highscore is: 1186
know that this line is wrong
resultHighScoreLabel.text = [NSString stringWithFormat:#"%i",highScore +10];
but I cannot figure how to make it work
any suggestions??
This is the quickfix:
int newHighscore = highScore+10;
int seconds = ((int)floor((newHighscore)/1000));
int milliseconds = newHighscore%1000;
resultHighScoreLabel.text = [NSString stringWithFormat:#"%is:%ims",seconds,milliseconds];
However I would highly recommend to change the way you handle the highscore

Converting seconds into hours, minutes, and seconds

I am making a stopwatch app. I am counting the time elapsed since the app was in the background, so that I can add it on to the stopwatch time when the app returns to the foreground. I have this code which is called when an NSNotification is sent to my StopwatchViewController with the elapsed time in seconds. I am trying to convert the seconds into hours, minutes and seconds:
-(void)newMessageReceived:(NSNotification *) notification
{
elapsedTime = [[notification object] intValue];
elapsedHours = elapsedTime / 3600;
elapsedTime = elapsedTime - (elapsedTime % 3600);
elapsedMinutes = elapsedTime / 60;
elapsedTime = elapsedTime - (elapsedTime % 60);
elapsedSeconds = elapsedTime;
secondInt = secondInt + elapsedSeconds;
if (secondInt > 59) {
++minuteInt;
secondInt -= 60;
}
minuteInt = minuteInt + elapsedMinutes;
if (minuteInt > 59) {
++hourInt;
minuteInt -= 60;
}
hourInt = hourInt + elapsedHours;
if (hourInt > 23) {
hourInt = 0;
}
}
The notification object is assigned to elapsedTime, but that is it; elapsedHours/minutes/seconds all stay at 0, and elapsedTime stays the same. Why isn't it working?
This approach seems overly complicated and error prone.
Why not just record the start time (as NSTimeInterval or NSDate) and subtract that from the current time to get the elapsed seconds?
You are subtracting off the wrong part from elapsedTime. You should be subtracting the hours not the remainder:
elapsedTime = elapsedTime - (elapsedTime / 3600) * 3600;
or you could use the equivalent calculation:
elapsedTime = elapsedTime % 3600;
Convert seconds in h m s with the usage of type conversion float to int
seconds = 111222333 # example
h = (seconds/60/60)
m = (h-int(h))*60
s = (m - int(m))*60
Check the result
print(f'{h:.0f} {m:.0f} {s:.0f}')

iOS Format String into minutes and seconds

I am receiving a string from the YouTube JSONC api, but the duration is coming as a full number i.e 2321 instead of 23:21 or 2 instead of 0:02. How would I go about fixing this?
JSON C
EDIT:
int duration = [videos valueForKey:#"duration"];
int minutes = duration / 60;
int seconds = duration % 60;
NSString *time = [NSString stringWithFormat:#"%d:%02d", minutes, seconds];
Assuming the duration value is really the duration in seconds, then you can calculate the number of minutes and seconds and then format those into a string.
int duration = ... // some duration from the JSON
int minutes = duration / 60;
int seconds = duration % 60;
NSString *time = [NSString stringWithFormat:#"%d:%02d", minutes, seconds];
You should use DateComponentsFormatter if the duration is intended to be user-facing:
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [ .minute, .second ]
formatter.zeroFormattingBehavior = [ .pad ]
let formattedDuration = formatter.string(from: duration)!
Try this very optimized
+ (NSString *)timeFormatConvertToSeconds:(NSString *)timeSecs
{
int totalSeconds=[timeSecs intValue];
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return [NSString stringWithFormat:#"%02d:%02d:%02d",hours, minutes, seconds];
}
int sec = diff;//INFO: time in seconds
int a_sec = 1;
int a_min = a_sec * 60;
int an_hour = a_min * 60;
int a_day = an_hour * 24;
int a_month = a_day * 30;
int a_year = a_day * 365;
NSString *text = #"";
if (sec >= a_year)
{
int years = floor(sec / a_year);
text = [NSString stringWithFormat:#"%d year%# ", years, years > 0 ? #"s" : #""];
sec = sec - (years * a_year);
}
if (sec >= a_month)
{
int months = floor(sec / a_month);
text = [NSString stringWithFormat:#"%#%d month%# ", text, months, months > 0 ? #"s" : #""];
sec = sec - (months * a_month);
}
if (sec >= a_day)
{
int days = floor(sec / a_day);
text = [NSString stringWithFormat:#"%#%d day%# ", text, days, days > 0 ? #"s" : #""];
sec = sec - (days * a_day);
}
if (sec >= an_hour)
{
int hours = floor(sec / an_hour);
text = [NSString stringWithFormat:#"%#%d hour%# ", text, hours, hours > 0 ? #"s" : #""];
sec = sec - (hours * an_hour);
}
if (sec >= a_min)
{
int minutes = floor(sec / a_min);
text = [NSString stringWithFormat:#"%#%d minute%# ", text, minutes, minutes > 0 ? #"s" : #""];
sec = sec - (minutes * a_min);
}
if (sec >= a_sec)
{
int seconds = floor(sec / a_sec);
text = [NSString stringWithFormat:#"%#%d second%#", text, seconds, seconds > 0 ? #"s" : #""];
}
NSLog(#"<%#>", text);
Here is the great code I finds for this
int duration = 1221;
int minutes = floor(duration/60)
int seconds = round(duration - (minutes * 60))
NSString * timeStr = [NSString stringWithFormat:#"%i:%i",minutes,seconds];
NSLog(#"Dilip timeStr : %#",timeStr);
And the output will belike this
Dilip timeStr : 20:21
You can subString the 2321 and get the first string as 23 and the second as 21 and convert them to int. Also check for the length of the text:
if (text.length < 4)
//add zeros on the left of String until be of length 4
Objective C:
NSDateComponentsFormatter * formatter = [[NSDateComponentsFormatter alloc]init];
[formatter setUnitsStyle:NSDateComponentsFormatterUnitsStyleShort];
[formatter setAllowedUnits:NSCalendarUnitSecond | NSCalendarUnitMinute];
[formatter setZeroFormattingBehavior:NSDateComponentsFormatterZeroFormattingBehaviorPad];
return [formatter stringFromTimeInterval:duration];

How to limit float Value in iOS

Now i am trying to get the length of Songs in iOS.
- (NSString *)returnofTotalLength
{
float duration = [[self.player.nowPlayingItem valueForProperty:MPMediaItemPropertyPlaybackDuration] floatValue]/60.0f;
NSString *length = [NSString stringWithFormat:#"%.2f",duration];;
NSString *totalLength = [length stringByReplacingOccurrencesOfString:#"." withString:#":"];
return totalLength;
}
above codes is the total length of song that show like 5:90.
You know that 5:90 can't be true because 60 seconds is 1 minute.
It's should be 6:30.
So i want to limit that value for 1 minute (60 seconds).
How can i do it Please help me?
Thanks.
This is simple math. Pseudocode:
minutes = (int)(seconds / 60);
rest = seconds % 60;
result = minutes:rest
Objc:
int seconds = 150;
int minutes = (int)(seconds / 60);
int rest = seconds % 60;
return [NSString stringWithFormat:#"%i:%i", minutes, rest];
do following :
min=(int)duration/60;
sec=duration%60;
than append minutes and second
If your time crosses to hours then you can go for this :
NSInteger seconds = duration % 60;
NSInteger minutes = (duration / 60) % 60;
NSInteger hours = duration / (60 * 60);
NSString *result = nil;
result = [NSString stringWithFormat:#"%02ld:%02ld:%02ld", hours, minutes, seconds];
I just got answer for my own question.
Thanks for other answers. :)
NSTimeInterval currentProgress = [[self.player.nowPlayingItem valueForProperty:MPMediaItemPropertyPlaybackDuration] floatValue];
float min = floor(currentProgress/60);
float sec = round(currentProgress - min * 60);
NSString *time = [NSString stringWithFormat:#"%02d:%02d", (int)min, (int)sec];
return time;
That will return NSString with Complete Format.

Resources