adding 0 in front of nsnumber - objective-c

I'm trying to save a month and the format needs to be 2 digits. The problem is the xcode is converting every month below October to 1 digit. How can I format the number so that it will be for example 01 for January?
Edit saving as a nsnumber. This is for an HTTP request call to stripe. The date that gets sent keeps changing from 0X to X for all months before October.
Edit 2 I'm also getting the following warning from where I convert the stripe card to a nsnumber
Implicit conversion loses integer precision:'NSUInteger' (aka 'unsigned long') to 'int'
Edit 3 To clarify, the number 01 keeps getting changed to 1. I want to save it as 01. How do I change the format of the number?

You could use either string formatting, or a number formatter. Either way, the output is going to be a string since you can't format the number its self. Here's an example:
NSNumber *number = #(9);
// using a number formatter
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterNoStyle];
[formatter setMinimumIntegerDigits:2];
NSString *numberString = [formatter stringFromNumber:number];
NSLog(#"%#",numberString);
// using string formatters
numberString = [NSString stringWithFormat:#"%02ld",(long)[number integerValue]];
NSLog(#"%#",numberString);

Related

Error when converting date string to NSObject

I'm sending details to a server which requires that I convert a date string into an NSDate object. The dictionary that will carry this object is declared like this
NSMutableDictionary *detailsRequest = [NSMutableDictionary dictionary];
Then the code which converts the date string to an object looks like this
[_dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[_dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSSZZZ"];
[_dateFormatter setAMSymbol:#"am"];
[_dateFormatter setPMSymbol:#"pm"];
[detailsRequest setObject:[_dateFormatter stringFromDate:[_dateFormatter dateFromString:val]] forKey:NDUserServerDateOfBirthKey];
The key NDUserServerDateOfBirthKey is declared as a constant like this
NSString * const NDUserServerDateOfBirthKey = #"dob";
The value for val is always '09/08/1987' and when it hits the last line it throws a SIGABRT error which says
2018-08-23 10:33:04.612769+0100 ClientCore[353:36543] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: dob)'
I've tried reducing the _dateFormatter to just [_dateFormatter setDateFormat:#"yyyy-MM-dd"]; but it still crashes with the same error. My string date always has a value so what is it I'm doing wrong?
The error occurs because the date format is wrong and the date string cannot be converted.
Please try to understand the format. The date string contains day (d), month (M) and year (y) slash separated – or month (M), day (d) and year (y) - but there is no letter T, no hyphens (-), no hours (H), no minutes (m), no seconds (s), no milliseconds (S), no timezone (Z) and no am/pm
The format is #"dd/MM/yyyy" or #"MM/dd/yyyy"
And why are you converting string to date and then immediately back to string?
If you want to convert dd/MM/yyyy to ISO8601 you need two different formats for input and output
NSString *val = #"09/08/1987";
NSDateFormatter *_dateFormatter = [[NSDateFormatter alloc] init];
_dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:#"en_US_POSIX"];
_dateFormatter.dateFormat = #"dd/MM/yyyy";
NSDate *date = [_dateFormatter dateFromString:val];
_dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH:mm:ssZZZ";
NSString *convertedString = [_dateFormatter stringFromDate:date];

NSNumberFormatter Scientific Form Output

I have NSNumber and NSResultFormatter, that converts number into string and displays it on screen.
In scientific form output for large numbers is "1.345e10" and for small numbers is "1.345e-10".
I want to output large numbers as "1.345e+10", like in standart iOS calc app. How can I to do it?
You can achieve that by setting a custom number format, for example:
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setExponentSymbol:#"e"];
[fmt setPositiveFormat:#"0.###E+0"];
NSString *s = [fmt stringFromNumber:#(12345678900)];
// 1.235e+10
Custom number formats are documented in http://www.unicode.org/reports/tr35/tr35-25.html#Number_Format_Patterns.

Convert back localized NSString number (> 4 digits) to integer

I used the localizedStringWithFormat: method on NSString class to convert a seven digit integer number to an NSString somewhere in my code and need to convert it back to an integer now.
As my App is localized for different regions with different separators after three digits (e.g. '.' in the U.S. and ',' in Germany), what's the best way to convert a localized NSString integer value to an integer?
I tried integerValue on my string as follows but it didn't work:
// Somewhere in code:
int num = 1049000;
NSString *myLocalizedNumString = [NSString localizedStringWithFormat:#"%d", num];
// myLocalizedNumString (U.S.): '1,049,000'
// myLocalizedNumString (Germany): '1.049.000'
// Somewhere else where I have a reference to my string but none to the num:
int restoredNum = [myLocalizedNumString integerValue];
// restoredNum isn't 1049000 (it's 0, the initial value)
What would be a good working way of doing it?
Despite its name NSNumberFormatter converts both ways, it is also a string parser. Using the method numberFromString after setting the number formatter’s numberStyle property to NSNumberFormatterDecimalStyle solves your problem.
The code might look as follows:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
NSInteger restoredNum = [[formatter numberFromString:myLocalizedNumString] integerValue];

How to round a float to 2 decimal places?

This is my algorithm to find out the speed of my game.
self.speed=.7-self.score/50;
Now how can I make self.speed round to 2 decimal places?
Note: my answer assumes you only care about the number of decimals for the purpose of displaying the value to the user.
When you setup your NSNumberFormatter to format the number into a string for display, setup the formatter with a maximum of two decimal places.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
NSString *formattedNumber = [formatter stringFromNumber:#(self.speed)];
You have the option of using the setRoundingMode: method if you need a specific round method.
BTW - you shouldn't use a string format for this because it doesn't take the user's locale into account to format the number properly.
floats are handled in IEEE754 format, you can't directly decide how many decimal places will be used.You can directly decide how many bits will be used, or indirectly round the las part of the number doing this:
NSString* str=[NSString stringWithFormat: #"%.2f", number];
number= atof([str UTF8String]);
But like maddy pointed, you only need to round/truncate the unwanted decimal digits only when presenting the number to the user, so you could only use the %.2f format specifier when printing it, or use a formatter.
self.speed = (int)(self.speed * 100 + 0.5) / 100.0;
if you want to have that as a string:
NSString *speedString = [NSString stringWithFormat: #"%.2f", self.speed];

Rounding behavior when NSNumberFormatter reads string?

I have this sample code:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSString *numberString = #"9.2";
NSNumber *number = [formatter numberFromString:numberString];
NSLog(#"String: %#, Number: %#", numberString, number);
The printed result is:
String: 9.2, Number: 9.199999999999999
I don't understand why this would happen. Am I missing a setting?
According to this reference, an NSNumber can store any ordinary C numeric type. Since this is obtained by parsing a non-integer, the two types to choose from are float and double, and by the displayed value, the chosen representation is double.
Since decimal fractions like 9.2 aren't exactly representable as doubles, you get the closest representable number. That is displayed to default precision, which is about 16 decimal places.