397

I'd like to convert an Int in Swift to a String with leading zeros. For example consider this code:

for myInt in 1 ... 3 {
    print("\(myInt)")
}

Currently the result of it is:

1
2
3

But I want it to be:

01
02
03

Is there a clean way of doing this within the Swift standard libraries?

Jeehut
  • 20,202
  • 8
  • 59
  • 80

12 Answers12

865

Assuming you want a field length of 2 with leading zeros you'd do this:

import Foundation

for myInt in 1 ... 3 {
    print(String(format: "%02d", myInt))
}

output:

01
02
03

This requires import Foundation so technically it is not a part of the Swift language but a capability provided by the Foundation framework. Note that both import UIKit and import Cocoa include Foundation so it isn't necessary to import it again if you've already imported Cocoa or UIKit.


The format string can specify the format of multiple items. For instance, if you are trying to format 3 hours, 15 minutes and 7 seconds into 03:15:07 you could do it like this:

let hours = 3
let minutes = 15
let seconds = 7
print(String(format: "%02d:%02d:%02d", hours, minutes, seconds))

output:

03:15:07
Fattie
  • 27,874
  • 70
  • 431
  • 719
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • 2
    Although this is not part of Swift it actually looks very clean. I think there just isn't a Swift native way of doing this so this might be the closest for now. Thank you, vacawama. :) – Jeehut Aug 29 '14 at 13:53
  • 1
    By the way: If I just wanted a single zero in front of my number I'd chose `println("0\(myInt)")` over your suggestion. That would use Swift native String class instead going through NSString formatting. – Jeehut Aug 29 '14 at 14:00
  • 9
    Is useful until you get to "10", hehe – Jose M Pan Jan 09 '15 at 23:53
  • How about two leading zeros for anything between 0 > 100 ? – codecowboy Jul 15 '15 at 05:05
  • 9
    `String(format: "%03d", myInt)` will give you `"000", "001", ... , "099", "100"`. – vacawama Jul 15 '15 at 09:56
  • Why don't use this String(format: "%02d:%02d", arguments:[1,2]) ? – frank Dec 24 '15 at 06:19
  • 1
    These's issue if value like `-3, -9` occurs, It still returns the same without a leading zero. – Codetard Sep 28 '18 at 07:59
  • @SatnamSync, indeed negative numbers need extra care because you need to make space for the `-` sign. You can extend the field width by 1 for negative numbers, or use `NumberFormatter` as described in part #3 of [this answer](https://stackoverflow.com/a/25567534/1630618). – vacawama Sep 28 '18 at 11:16
  • Yes, I implemented a negative integer check with if else statement. Your answer is very helpful. Thanks. – Codetard Sep 28 '18 at 12:00
186

With Swift 5, you may choose one of the three examples shown below in order to solve your problem.


#1. Using String's init(format:_:) initializer

Foundation provides Swift String a init(format:_:) initializer. init(format:_:) has the following declaration:

init(format: String, _ arguments: CVarArg...)

Returns a String object initialized by using a given format string as a template into which the remaining argument values are substituted.

The following Playground code shows how to create a String formatted from Int with at least two integer digits by using init(format:_:):

import Foundation

let string0 = String(format: "%02d", 0) // returns "00"
let string1 = String(format: "%02d", 1) // returns "01"
let string2 = String(format: "%02d", 10) // returns "10"
let string3 = String(format: "%02d", 100) // returns "100"

#2. Using String's init(format:arguments:) initializer

Foundation provides Swift String a init(format:arguments:) initializer. init(format:arguments:) has the following declaration:

init(format: String, arguments: [CVarArg])

Returns a String object initialized by using a given format string as a template into which the remaining argument values are substituted according to the user’s default locale.

The following Playground code shows how to create a String formatted from Int with at least two integer digits by using init(format:arguments:):

import Foundation

let string0 = String(format: "%02d", arguments: [0]) // returns "00"
let string1 = String(format: "%02d", arguments: [1]) // returns "01"
let string2 = String(format: "%02d", arguments: [10]) // returns "10"
let string3 = String(format: "%02d", arguments: [100]) // returns "100"

#3. Using NumberFormatter

Foundation provides NumberFormatter. Apple states about it:

Instances of NSNumberFormatter format the textual representation of cells that contain NSNumber objects and convert textual representations of numeric values into NSNumber objects. The representation encompasses integers, floats, and doubles; floats and doubles can be formatted to a specified decimal position.

The following Playground code shows how to create a NumberFormatter that returns String? from a Int with at least two integer digits:

import Foundation

let formatter = NumberFormatter()
formatter.minimumIntegerDigits = 2

let optionalString0 = formatter.string(from: 0) // returns Optional("00")
let optionalString1 = formatter.string(from: 1) // returns Optional("01")
let optionalString2 = formatter.string(from: 10) // returns Optional("10")
let optionalString3 = formatter.string(from: 100) // returns Optional("100")
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
  • I think your answer is right when you want to format numbers the same way at multiple places. As I didn't ask for that I've chosen vacawama's answer as the correct but. But thank you for the answer! :) – Jeehut Aug 29 '14 at 13:57
  • @ImanouPetit. FYI, I used this with minimum number digits 3. If I don't explicitly unwrap i.e. let formattedNumber = formatter.stringFromNumber(counter)! then the strings contain Optional("001") so my code to dynamically choose an image path fails. Unwrapping with '!" solves the problem – codecowboy Jul 15 '15 at 05:13
19

For left padding add a string extension like this:

extension String {

    func padLeft(totalWidth: Int, with byString: String) -> String {
        let toPad = totalWidth - self.count
        if toPad < 1 {
            return self
        }
    
        return "".padding(toLength: toPad, withPad: byString, startingAt: 0) + self
    }
}

Using this method:

for myInt in 1...3 {
    print("\(myInt)".padLeft(totalWidth: 2, with: "0"))
}
Kiran P Nair
  • 2,041
  • 22
  • 31
10

Swift 3.0+

Left padding String extension similar to padding(toLength:withPad:startingAt:) in Foundation

extension String {
    func leftPadding(toLength: Int, withPad: String = " ") -> String {

        guard toLength > self.characters.count else { return self }

        let padding = String(repeating: withPad, count: toLength - self.characters.count)
        return padding + self
    }
}

Usage:

let s = String(123)
s.leftPadding(toLength: 8, withPad: "0") // "00000123"
John Cromie
  • 181
  • 2
  • 4
  • 1
    This may or may not work as the user expects if the `withPad` argument passed is more than a single character. – nhgrif Aug 07 '17 at 13:17
7

Swift 5

@imanuo answers is already great, but if you are working with an application full of number, you can consider an extension like this:

extension String {

    init(withInt int: Int, leadingZeros: Int = 2) {
        self.init(format: "%0\(leadingZeros)d", int)
    }

    func leadingZeros(_ zeros: Int) -> String {
        if let int = Int(self) {
            return String(withInt: int, leadingZeros: zeros)
        }
        print("Warning: \(self) is not an Int")
        return ""
    }
    
}

In this way you can call wherever:

String(withInt: 3) 
// prints 03

String(withInt: 23, leadingZeros: 4) 
// prints 0023

"42".leadingZeros(2)
// prints 42

"54".leadingZeros(3)
// prints 054
Community
  • 1
  • 1
Luca Davanzo
  • 21,000
  • 15
  • 120
  • 146
  • extensions FTW..!! This also worked fine in Swift 4. For those of us struggling to move older code from 3, to 4, and eventually to Swift 5... :) – Nick N Sep 13 '19 at 14:55
  • 1
    the naming is totally wrong. "leading zeros" does not give you "leading zeros". it gives you a string that long. – Fattie Apr 16 '23 at 15:39
  • Feel free to suggest something else and edit answer if it makes you feel better. "fillWithInitialZerosTheStringLenght(2)" should be better? – Luca Davanzo Apr 20 '23 at 09:35
6

Using Swift 5’s fancy new extendible interpolation:

extension DefaultStringInterpolation {
    mutating func appendInterpolation(pad value: Int, toWidth width: Int, using paddingCharacter: Character = "0") {
        appendInterpolation(String(format: "%\(paddingCharacter)\(width)d", value))
    }
}

let pieCount = 3
print("I ate \(pad: pieCount, toWidth: 3, using: "0") pies")  // => `I ate 003 pies`
print("I ate \(pad: 1205, toWidth: 3, using: "0") pies")  // => `I ate 1205 pies`
mxcl
  • 26,392
  • 12
  • 99
  • 98
4

The other answers are good if you are dealing only with numbers using the format string, but this is good when you may have strings that need to be padded (although admittedly a little diffent than the question asked, seems similar in spirit). Also, be careful if the string is longer than the pad.

   let str = "a str"
   let padAmount = max(10, str.count)
   String(repeatElement("-", count: padAmount - str.count)) + str

Output "-----a str"

possen
  • 8,596
  • 2
  • 39
  • 48
3

in Xcode 8.3.2, iOS 10.3 Thats is good to now

Sample1:

let dayMoveRaw = 5 
let dayMove = String(format: "%02d", arguments: [dayMoveRaw])
print(dayMove) // 05

Sample2:

let dayMoveRaw = 55 
let dayMove = String(format: "%02d", arguments: [dayMoveRaw])
print(dayMove) // 55
Steffen
  • 161
  • 1
  • 5
3

The below code generates a 3 digits string with 0 padding in front:

import Foundation

var randomInt = Int.random(in: 0..<1000)
var str = String(randomInt)
var paddingZero = String(repeating: "0", count: 3 - str.count)

print(str, str.count, paddingZero + str)

Output:

5 1 005
88 2 088
647 3 647
n a
  • 47
  • 3
0

Swift 4* and above you can try this also:

func leftPadding(valueString: String, toLength: Int, withPad: String = " ") -> String {
        guard toLength > valueString.count else { return valueString }
        
        let padding = String(repeating: withPad, count: toLength - valueString.count)
        return padding + valueString
    }

call the function:

leftPadding(valueString: "12", toLength: 5, withPad: "0")

Output: "00012"

Anupam Mishra
  • 3,408
  • 5
  • 35
  • 63
-1

Details

Xcode 9.0.1, swift 4.0

Solutions

Data

import Foundation

let array = [0,1,2,3,4,5,6,7,8]

Solution 1

extension Int {

    func getString(prefix: Int) -> String {
        return "\(prefix)\(self)"
    }

    func getString(prefix: String) -> String {
        return "\(prefix)\(self)"
    }
}

for item in array {
    print(item.getString(prefix: 0))
}

for item in array {
    print(item.getString(prefix: "0x"))
}

Solution 2

for item in array {
    print(String(repeatElement("0", count: 2)) + "\(item)")
}

Solution 3

extension String {

    func repeate(count: Int, string: String? = nil) -> String {

        if count > 1 {
            let repeatedString = string ?? self
            return repeatedString + repeate(count: count-1, string: repeatedString)
        }
        return self
    }
}

for item in array {
    print("0".repeate(count: 3) + "\(item)")
}
Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
  • Like your repeatElement approach, see my answer for padding strings. – possen May 06 '18 at 08:35
  • These will not work for two digit ints (eg. 10 becomes 010). Also the original question asked specifically for solutions involving Standard Libraries. The answer above by @ImanouPetit is preferred. – cleverbit Dec 30 '18 at 14:03
-12

Unlike the other answers that use a formatter, you can also just add an "0" text in front of each number inside of the loop, like this:

for myInt in 1...3 {
    println("0" + "\(myInt)")
}

But formatter is often better when you have to add suppose a designated amount of 0s for each seperate number. If you only need to add one 0, though, then it's really just your pick.

Eric Zhou
  • 925
  • 1
  • 6
  • 6