timeIntervalSinceNow returning random numbers - iphone

timeInterval keeps returning random numbers. I would think the interval would continue to increase with each call but sometimes I get negative numbers and sometimes positive numbers.
NSDate *date = groceryItem.lastPurchased;
double timeInterval = [date timeIntervalSinceNow];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d", timeInterval];

%d is for integers, use %f for double
[NSString stringWithFormat:#"%f", timeInterval];

Try this instead:
NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:groceryItem.lastPurchased];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f", timeInterval];
A few points on this snippet:
I've used NSTimeInterval instead of double in the second line. They are equivalent because it's just a typedef but it makes for clearer code.
Rather than getting the time interval from a date in the past, I'm calculating the date and time right now with [NSDate date] and getting the time interval from groceryItem.lastPurchased. This will return a postive number as long as groceryItem.lastPurchased is in the past.
I've edited my original code to pass groceryItem.lastPurchased to the time interval calculation directly. It isn't always a good idea to declare a variable for an item that is going to be used only once, especially in non-garbage-collected environments. Although declaring variables might make the code more readable there are other ways of improving readability. For example, in this case change the property to groceryItem.lastPurchasedDate which makes it a lot clearer.

If the receiver is earlier than the current date and time, the return value is negative. so if date is before now it will be negative.

timeIntervalSinceNow will return the interval between the receiver and the current date and time. If the receiver is earlier than the current date and time, the return value is negative. If the receiver is later than the current date and time, the return value is positive.
Hope this helps.

This code [NSString stringWithFormat:#"%d", timeInterval]; is wrong. It is a DOUBLE. don't use %d. Use %f instead.
[NSString stringWithFormat:#"%f", timeInterval];

It has been answered correctly above, I'd also add you should use the NSTimeInterval type rather than double as well.

You should use a negative sign as below
double timeInterval = - [date timeIntervalSinceNow];

Related

Formatting number with NSNumberFormatter that already has decimals and thousand seperators

I have these number formats:
100000,459
100000459
100.000
100.000,59
100.000.000,39
The number changes as the user input values to it. And for every value added, I need to re-format the number with NSNumberFormatter. The problem is that this number already has . and , and the formatter does not seem to handle these correctly. It comes out like this:
100 000,00
100 000 459,00
100,00
100,00
100,00
E.g. I want 100000,459 to become 100 000,459.
The code I use now:
NSNumber *amount = [NSNumber numberWithInt:[string intValue]];
NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"nb_NO"];
[currencyFormatter setLocale:locale];
NSString *commaString = [currencyFormatter stringForObjectValue:amount];
How can I format already formatted numbers?
In the last line you are trying to format a string rather than a number. Try this:
NSString *commaString = [currencyFormatter stringFromNumber:amount];
Here is a good reference.
I've looked at that specific reference. It differs from my problem because in my case I may already have decimals when formatting.
NSNumberFormatter formats a number to a string representation and it needs the correct representation of the number to be able to format it as expected. By the look of your code sample you are providing the formatter with an integer value and that is why you are getting the output you are getting. With string = #"100000,459" [string intValue] gives you 100000. Which is why the output from the formatter is 100 000,00.
What you need to do is to first get the string into a double representation. That can be achieved by using NSScanner. You just have to make sure that you scan the numbers in the correct locale so the thousand separators are detected properly. Your first string can be converted to a double by:
NSScanner *scanner = [NSScanner scannerWithString:#"100000,459"];
[scanner setLocale:locale];
double val;
[scanner scanDouble:&val];
NSNumber *amount = [NSNumber numberWithDouble:val];
How to properly handle the thousand separators I don't know.

Examples of doing decimal math in iPhone

I'm pulling decimal values from a sql table as a text field which i then convert to an NSDecimalNumber (this is simply because i didnt know read/write decimal values to sqllite).
Anyway, now i've hit a wall now that im trying to do simple math routines on these decimal variables. Such as, Sum = Balance * Interest_Rate. The idea is that im working with money calculations.
Do you know of samples/tutorials that teaches how to do these operations using either NSDecimal, NSDecimalNumber, or both?
Thanks.
To init:
NSString *number = #"123.4";
NSDecimalNumber *myDecimal = [[NSDecimalNumber alloc] initWithString: number];
To do what you want to do:
NSDecimalNumber *sum = [[NSDecimalNumber alloc] initWithDecimal:[balance decimalNumberByMultiplyingBy: interest_rate];
How?
Well you make a NSDecimalNumber and alloc and then initWithDecimal. What decimal? balance multiplied (decimalNumberByMultiplyingBy) by interest_rate.

Displaying timecode using NSTimer and NSDateFormatter

I am very close to completing my first iphone app and it has been a joy. I am trying to add running timecode using the current time via an NSTimer displaying the current time (NSDate) on a UILabel. NSDate is working fine for me, showing hour, minute, second, milliseconds. But instead of milliseconds, I need to show 24 frames per second.
The problem is that I need the frames per second to be synced 100% with the hour, minute and second, so I can't add the frames in a separate timer. I tried that and had it working but the frame timer was not running in sync with the date timer.
Can anyone help me out with this? Is there a way to customize NSDateFormatter so that I can have a date timer formatted with 24 frames per second? Right now I'm limited to formatting just hours, minutes, seconds, and milliseconds.
Here's the code I'm using right now
-(void)runTimer {
// This starts the timer which fires the displayCount method every 0.01 seconds
runTimer = [NSTimer scheduledTimerWithTimeInterval: .01
target: self
selector: #selector(displayCount)
userInfo: nil
repeats: YES];
}
//This formats the timer using the current date and sets text on UILabels
- (void)displayCount; {
NSDateFormatter *formatter =
[[[NSDateFormatter alloc] init] autorelease];
NSDate *date = [NSDate date];
// This will produce a time that looks like "12:15:07:75" using 4 separate labels
// I could also have this on just one label but for now they are separated
// This sets the Hour Label and formats it in hours
[formatter setDateFormat:#"HH"];
[timecodeHourLabel setText:[formatter stringFromDate:date]];
// This sets the Minute Label and formats it in minutes
[formatter setDateFormat:#"mm"];
[timecodeMinuteLabel setText:[formatter stringFromDate:date]];
// This sets the Second Label and formats it in seconds
[formatter setDateFormat:#"ss"];
[timecodeSecondLabel setText:[formatter stringFromDate:date]];
//This sets the Frame Label and formats it in milliseconds
//I need this to be 24 frames per second
[formatter setDateFormat:#"SS"];
[timecodeFrameLabel setText:[formatter stringFromDate:date]];
}
I would suggest that you extract the milliseconds from your NSDate - this is in seconds, so the fraction will give you milliseconds.
Then just use a plain format string to append the value using NSString method stringWithFormat:.
Lots-a-overhead with NSFormatter + NSDate. Plus it seems to me that NSDate doesn't provide a "simple" microtime situation for simple stuff.
Mogga provided a nice pointer, here's a C / Objective-C variant:
- (NSString *) formatTimeStamp:(float)seconds {
int sec = floor(fmodf(seconds, 60.0f));
return [NSString stringWithFormat:#"%02d:%02d.%02d.%03d",
(int)floor(seconds/60/60), // hours
(int)floor(seconds/60), // minutes
(int)sec, // seconds
(int)floor((seconds - sec) * 1000) // milliseconds
];
}
// NOTE: %02d is C style formatting where:
// % - the usual suspect
// 02 - target length (pad single digits for padding)
// d - the usual suspect
See this discussion for more info on this formatting.
Here's a Processing/Java equivalent that's fairly straightforward to repurpose.
String timecodeString(int fps) {
float ms = millis();
return String.format("%02d:%02d:%02d+%02d", floor(ms/1000/60/60), // H
floor(ms/1000/60), // M
floor(ms/1000%60), // S
floor(ms/1000*fps%fps)); // F
}

calculating total time of downloading data?

i am using apple's sample URLCache,but when i mention url, it loads data perfectly
but i want to calculate time of downloading(till completion),is there anyh built in method?
Add NSDate property to your class, name it,let's say, downloadStart and when download starts, save actual time to it - self.downloadStart = [NSDate date];
Then in -connectionDidFinishLoading: delegate method implementation do:
NSDate *downloadEnd = [NSDate date];
NSTimeInterval totalTime = ([downloadEnd timeIntervalSince1970] - [downloadStart timeIntervalSince1970]);
//Total time now contains number of seconds since download start time
NSLog(#"Download finished in %f seconds", totalTime);
self.downloadStart = nil;
That's it. Please note that the code above is just a kind of abstract how to do the trick, so don't use in copy & paste manner.

How to obtain an unformatted string representation of an NSDecimal or NSDecimalNumber?

I have an NSDecimal and need this as technical string, i.e. with no formatting in any way. Floating point should be a "." if there is any, and minus sign should just be a "-" if there is any. besides that, there should be no formatting going on like grouping or chinese numbers.
I was looking for 2 hours through the SDK but it seems there is nothing simple to accomplish this. Are there solutions for this?
For NSDecimal, you can use NSDecimalString with a specified locale:
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
NSString *decimalString = NSDecimalString(&decimalValue, usLocale);
[usLocale release];
The U.S. locale uses a period for the decimal separator, and no thousands separator, so I believe that will get you the kind of formatting you're looking for.
As others have pointed out, for an NSDecimalNumber you can use the -descriptionWithLocale: method with the above-specified U.S. locale. This doesn't lose you any precision.
NSDecimalNumber
NSLog(#"%#", [theNumber stringValue]);
NSDecimal
NSLog(#"%#", NSDecimalString(&theDecimal, nil));
NSDecimalNumber is a subclass of NSNumber which has the -stringValue method.
stringValue
Returns the receiver’s
value as a human-readable string.
- (NSString *)stringValue
Return Value
The receiver’s value as a
human-readable string, created by
invoking descriptionWithLocale: where
locale is nil.
descriptionWithLocale:
Returns a string that represents the contents of
the receiver for a given locale.
- (NSString *)descriptionWithLocale:(id)aLocale
Parameters aLocale
An object
containing locale information with
which to format the description. Use
nil if you don’t want the description
formatted.
Just call [theNumber stringValue].
Use decimalNumberWithString from the NSDecimalNumber class:
NSDecimalNumber *dn = [NSDecimalNumber decimalNumberWithMantissa:12345
exponent:-100
isNegative:YES];
NSDictionary *local = nil;
NSString *ds = [dn descriptionWithLocale: local];
NSLog(#"dn: %#", dn);
NSLog(#"ds: %#", ds);
dn: -0.00000000000000000000000 … 0000000000000000000000000000000000012345
ds: -0.00000000000000000000000 … 0000000000000000000000000000000000012345