Swift 4 String formatter to currency - swift

I have string 99897.05 and I want to convert it like this 99 897.05
example:
input: 8121.1
output 8 121.1
input 111111.11
output 111 111.11

What you need is the currencyGroupingSeparator:
let amount = 99897.05
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyGroupingSeparator = " "
formatter.string(for: amount) //"$99 897.05"
You could change it whatever you'd like:
formatter.currencyGroupingSeparator = "💵"
formatter.string(for: amount) //"$99💵897.05"

Related

NSNumberFormatter and .floor roundingMode

Can someone tell me why this happening?
let formatter = NumberFormatter.init()
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
formatter.roundingMode = .floor
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
let v = 36
let scale = 10
let float = formatter.string(from: NSNumber(value: Float(v) / Float(scale)))!
let double = formatter.string(from: NSNumber(value: Double(v) / Double(scale)))!
print(float) // 3.59
print(double) // 3.60
When I use Float the result is 3.59 (wrong result in my opinion) and when I use Double the result is 3.60.
I know it is something related to .floor roundingMode, but i don't fully understand the reason.
If you would like to preserve your fraction digits precision it is better to use Swift native Decimal type. That's what it is. You can use the Decimal init(sign: FloatingPointSign, exponent: Int, significand: Decimal) initializer and use your scale exponent and your value significand. Just make sure to negate its value:
extension SignedInteger {
var negated: Self { self * -1 }
}
let v = 36
let scale = 10
let sign: FloatingPointSign = v >= 0 ? .plus : .minus
let exponent = Decimal(scale).exponent.negated
let significand = Decimal(v).significand
let decimal = Decimal.init(sign: sign, exponent: exponent, significand: significand)
let formatted = formatter.string(for: decimal) // "3.60"

DateIntervalFormatter: string of format "m:ss"

I'd like to get a string of format "m:ss" out of two dates.
E.g.: "0:27" for 27 seconds difference and "1:30" for 90 seconds difference between dates.
Here's the code I'm using:
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .none
formatter.dateTemplate = "m:ss"
let startDate = Date()
let endDate = Date(timeInterval: 1, since: startDate)
let outputString = formatter.string(from: startDate, to: endDate)
print(outputString) //16:12 – 16:13 ???
// This is correct, but it doesn't actually calculate the interval.
But I'm getting just two dates printed out with a dash.
How can I actually make the DateIntervalFormatter to calculate the difference as I want?
The code is almost 1:1 sample from the Apple documentation but with the custom dateTemplate: https://developer.apple.com/documentation/foundation/dateintervalformatter
It seems that you actually want DateComponentsFormatter
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.minute, .second]
formatter.zeroFormattingBehavior = .pad
let startDate = Date()
let endDate = Date(timeInterval: 129, since: startDate)
let outputString = formatter.string(from: startDate, to: endDate)!
print(outputString)
to remove the leading zero if the minutes are < 10 you could use Regular Expression
print(outputString.replacingOccurrences(of: "^0(\\d)", with: "$1", options: .regularExpression))
I created this solution which doesn't involve the DateIntervalFormatter:
import Foundation
let minutes = 2
let seconds = 9
let formatted = String(format: "%01d:%02d", minutes, seconds)
print(formatted) // 2:09
Looks like what DateIntervalFormatter does is just applying a standard Date->String conversion to both of the dates and adds a dash between them.

Swift. How to set custom number format? With space thouthand separator and two digits after point

I need separate thouthands with space, and two digit after point.
let d1: Double = 20000000.0
let d2: Double = 1.2345
I want to view:
let s1 = String(format: "????", d1) //20 000 000.00
let s2 = String(format: "????", d2) //1.23
How to do it?
let d1: Double = 20000000.0
let d2: Double = 1.2345
let formatter = NumberFormatter()
formatter.groupingSeparator = " "
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
formatter.decimalSeparator = "." // Default separator is dependent to the current local.
print(formatter.string(for: d1)) // 20 000 000.00
print(formatter.string(for: d2)) // 1.23

When rounding swift double it shows different numbers

When I got two numbers, like 5.085 and 70.085. My code rounds the first number to 5.09, but the second one it goes to 70.08. For some reason, when making let aux1 = aux * 100 the value goes to 7008.49999999. Any one have the solution to it?
Here is my code:
let aux = Double(value)!
let aux1 = aux * 100
let aux2 = (aux1).rounded()
let number = aux2 / 100
return formatter.string(from: NSNumber(value: number))!
If you want to format the Double by rounding it's fraction digits. Try't:
First, implement this method
func formatDouble(_ double: Double, withFractionDigits digits: Int) -> String{
let formatter = NumberFormatter()
formatter.maximumFractionDigits = digits
let string = formatter.string(from: (NSNumber(floatLiteral: double)))!
return string
/*if you want a Double instead of a String, change the return value and uncomment the bellow lines*/
//let number = formatter.number(from: string)!
//return number.doubleValue
}
after, you can call't that way
let roundedNumber = formatDouble(Double(value)!, withFractionDigits: 2)

Swift: String to ints without special function

I'm searching for a build-in function for converting a string like
"01092030" (format "[[dd]hh]mmss") to four individual integers.
dd => 01
hh => 09
mm => 20
ss => 30
dd and hh are optional. If missing they should be 0. I could do it by by developing a special function, but I like to use something like a regular expression.
I don't see the point of your "build-in function" or "regular expression" requirements, but whatever...
let s = "092030" as NSString
let pattern = "\\d\\d"
let reg = try! NSRegularExpression(pattern: pattern, options: [])
let matches = reg.matchesInString(s as String, options: [], range: NSMakeRange(0, s.length))
var result = matches.map {s.substringWithRange($0.range)}
while result.count < 4 {
result.insert("0", atIndex: 0)
}
// result is: ["0", "09", "20", "30"]
I'm also a little unclear on your output requirements. On the one hand, you say you want four "individual integers". But "09" is not an integer; it's a string representing an integer. So it seems to me that you actually want strings. If so, then result is the desired result. If not, then you need one more step:
let result2 = result.map{Int($0)!}
// result2 is: [0, 9, 20, 30]
Since the string contains date components you could alternatively use NSDateFormatter
let string = "01092030"
let dateFormatter = NSDateFormatter()
let dayMissing = string.characters.count < 8
let hourMissing = string.characters.count < 6
dateFormatter.dateFormat = hourMissing ? "mmss" : dayMissing ? "HHmmss" : "ddHHmmss"
let date = dateFormatter.dateFromString(string)!
let components = NSCalendar.currentCalendar().components([.Day, .Hour, .Minute, .Second], fromDate: date)
let second = components.second
let minute = components.minute
let hour = components.hour
let day = dayMissing ? 0 : components.day