Trying to work out where I have screwed up with trying to create a count down timer which displays seconds and milliseconds. The idea is the timer displays the count down time to an NSString which updates a UILable.
The code I currently have is
-(void)timerRun {
if (self.timerPageView.startCountdown) {
NSLog(#"%i",self.timerPageView.xtime);
self.timerPageView.sec = self.timerPageView.sec - 1;
seconds = (self.timerPageView.sec % 60) % 60 ;
milliseconds = (self.timerPageView.sec % 60) % 1000;
NSString *timerOutput = [NSString stringWithFormat:#"%i:%i", seconds, milliseconds];
self.timerPageView.timerText.text = timerOutput;
if (self.timerPageView.resetTimer == YES) {
[self setTimer];
}
}
else {
}
}
-(void)setTimer{
if (self.timerPageView.xtime == 0) {
self.timerPageView.xtime = 60000;
}
self.timerPageView.sec = self.timerPageView.xtime;
self.timerPageView.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(timerRun) userInfo:Nil repeats:YES];
self.timerPageView.resetTimer = NO;
}
int seconds;
int milliseconds;
int minutes;
}
Anyone got any ideas what I am doing wrong?
You have a timer that will execute roughly 100 times per second (interval of 0.01).
You decrement a value by 1 each time. Therefore, your self.timerPageView.sec variable appears to be hundredths of a second.
To get the number of seconds, you need to divide this value by 100. To get the number of milliseconds, you need to multiply by 10 then modulo by 1000.
seconds = self.timerPageView.sec / 100;
milliseconds = (self.timerPageView.sec * 10) % 1000;
Update:
Also note that your timer is highly inaccurate. The timer will not repeat EXACTLY every hundredth of a second. It may only run 80 times per second or some other inexact rate.
A better approach would be to get the current time at the start. Then inside your timerRun method you get the current time again. Subtract the two numbers. This will give the actual elapsed time. Use this instead of decrementing a value each loop.
You set a time interval of 0.01, which is every 10 milliseconds, 0.001 is every millisecond.
Even so, NSTimer is not that accurate, you probably won't get it to work every 1 ms. It is fired from the run loop so there is latency and jitter.
These calculations look pretty suspect:
seconds = (self.timerPageView.sec % 60) % 60 ;
milliseconds = (self.timerPageView.sec % 60) % 1000;
You are using int type calculations (pretty sketchy in their implementation) on a float value for seconds.
NSUInteger seconds = (NSUInteger)(self.timerPageView.sec * 100); //convert to an int
NSUInteger milliseconds = (NSUInteger) ((self.timerPageView.sec - seconds)* 1000.);
Related
Modified Question.
My fitness app will calculate the number of calories burned based on a calculated value for each second. I have a timer that will allow the app to pick back up should it. I can't get the running sum to continue calculating when the app goes into the background. I tried to place the running sum inside of a DispatchQueue but not getting the sum as expected. Any guidance is greatly appreciated.
Here's the code I have placed inside the function that updates the timer.
//MARK: - Update Timer Label
func updateTimerLabel() {
interval = -Int(timerStartDate.timeIntervalSinceNow)
time = interval
let hours = interval / 3600
let minutes = interval / 60 % 60
let seconds = interval % 60
print("Current interval = \(interval)")
timerLabel.text = String(format:"%02i:%02i:%02i", hours, minutes, seconds)
DispatchQueue.global(qos: .background).async {
if self.activityArray[self.currentArrayRow].2 <= 4.5 {
self.cps = self.activityArray[self.currentArrayRow].2 * Double(self.user.userWeightInKilo) / 3600
self.runningCPS = self.runningCPS + self.cps
print("MET \(self.activityArray[self.currentArrayRow].2) <= 4.5 * KG (\(Double(self.user.userWeightInKilo))) * HR (\(Double(self.user.userHeartRate))) / MaxHR (\(Double(self.user.maxHeartRate)) * interval \(Double(self.interval)) / 3600. Gives a cps 0f \(self.cps) and a runningCPS of \(self.runningCPS) ")
} else {
self.cps = self.activityArray[self.currentArrayRow].2 * Double(self.user.userWeightInKilo) * Double(self.user.userHeartRate) / Double(self.user.maxHeartRate) / 3600
self.runningCPS = self.runningCPS + self.cps
print("MET \(self.activityArray[self.currentArrayRow].2) > 4.5 * KG (\(Double(self.user.userWeightInKilo))) * HR (\(Double(self.user.userHeartRate))) / MaxHR (\(Double(self.user.maxHeartRate)) * interval \(Double(self.interval)) / 3600. Gives a cps 0f \(self.cps) and a runningCPS of \(self.runningCPS) ")
}
}
activeLabel.text = String(format: "%0.1f", runningCPS) + " Calories Burned"
}
I have the following function:
function timestamp(duration)
local hours = duration / 3600
local minutes = duration % 3600 / 60
local seconds = duration % 60
return string.format("%02d:%02d:%02.03f", hours, minutes, seconds)
end
when the duration is 4.404 sec it returns 00:00:4.404
what is am looking for is 00:00:04.404
It should be:
string.format("%02d:%02d:%06.3f", hours, minutes, seconds)
Field width contains all characters of the number, including point and fraction.
My Timer is displaying Minutes and Hours, but once it gets to 60 minutes it restarts from 0 Minute.
Should I get rid of the modulo ( % 60 ) for minutes.
I would like my timer to display for ex: 80:45 ( basically not stopping at 60 min once it reaches 1 hour)
var min = 0
var sec = 0
func stringFromTimeInterval(interval: NSTimeInterval) -> String {
let interval = Int(interval)
let seconds = interval % 60
let minutes = (interval / 60) % 60
//let hours = (interval / 3600)// I don't need the hours
return String(format: "%02d:%02d",minutes, seconds)
}
% 60 means that it will spit out a minutes value that is the remainder when divided by 60(minutes). This is most probably because for time in the form hh:mm, you want it to go from 5:59 to 6:00, not 5:60. So changing the following line will give you what you seek.
let minutes = (interval / 60) % 60 -> let minutes = interval / 60
I'm attempting to convert MPH into minute miles. I'm currently running code to do this by doing 60 / the miles per hour which gives me the result in minute miles.
For example 60/8mph = 7.5
However the answer I get I need to convert into minutes and seconds so that I would have 7 minutes 30 seconds. Is there a way I can get the numbers after the decimal point so I can multiply it by 60 to convert it to seconds, then add it back to the minutes.
You can use remainder,
double remainder = fmod(a_double, another_double);
should include <math.h>
Well, I don't know whether there is an existing class that handles this, but to answer your specific question, the fractional part of the decimal (mantissa?) would be:
((60 % 8) / 8.0f)
You can multiply that by 60.
Do it in seconds...
3600/8 = 450
450/60 = 7 remainder 30
= 7:30
It's pretty simple, you're on the right path actually.
What you need to do is:
Get Minutes
Get Seconds
Convert seconds from int to real time (0.5 to 30, etc..)
Add seconds to minutes
Get minutes by casting it to an Integer:
int minutes = 60/8;
Get seconds by using the remainder:
float seconds = 60%8;
Convert seconds to real time:
int realSeconds = seconds * 60;
Now get result back by adding both:
int totalSeconds = minuts + realSeconds;
Here's a little function that does it (typed directly to browser, probably won't compile)
#include <math.h>
int getMinuteMiles(float mph){
int minutes = 60/mph;
double seconds = fmod(60, mph);
int realSeconds = seconds * 60;
return minutes+realSeconds;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
This is stupid, but i have to know how ( % ) sign means, because i want to add days.
this is an example.
int seconds = 78120;
int forHours = (seconds1 / 3600),
remainder = (seconds1 % 3600),
forMinutes = remainder / 60,
forSeconds = remainder % 60;
NSString *Time = [NSString stringWithFormat:#"%02i:%02i:%02i",forHours,forMinutes,forSeconds];
Label.text = Time;
Result:
21:42:00
i want the result to be like ( 0 days, 21:42:00 ) like ( DD, HH:mm:ss )
It's called the modulo operation. It's whats left when you divide a number (and only take into account whole numbers).
Examples:
3 % 2 = 1
6 % 2 = 0
6 % 3 = 0
6 % 4 = 2
% (modulo) gives the remainder after division.
So you can add the separation for days at the start, then use modulo to get the number of seconds after removing those accounted for in days:
int seconds = 78120;
int days = seconds / 86400;
// Equivalent to: seconds = seconds - days * 86400 /*# seconds in a day*/;
seconds = seconds % 86400; // seconds remaining less than a day
int forHours = (seconds1 / 3600),
remainder = (seconds1 % 3600), // seconds remaining within an hour
forMinutes = remainder / 60,
forSeconds = remainder % 60; // seconds remaining less than a minute
The modulus (%) operator returns the remainder of the integer division.
a = 13 % 5;
Here, a will equal 3.
Try:
int fordays = seconds1 / 86400,
remainder = seconds1 % 86400,
forHours = remainder / 3600,
remainder = remainder % 3600,
forMinutes = remainder / 60,
forSeconds = remainder % 60;
1 day = 86400 seconds.