Roman Podymov
Roman Podymov

Reputation: 4541

How to make the first word of DateComponentsFormatter.string(from:)'s result capitalised?

In my iOS project I have a function to convert an integer value to string with the "seconds" postfix:

func secondsToString(_ seconds: Int) -> String {    
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full
    formatter.allowedUnits = [.second]
    return formatter.string(from: DateComponents(second: seconds)) ?? ""
}

And this is how I call it:

print(secondsToString(10)) // Output is "10 seconds"
print(secondsToString(1)) // Output is "1 second"

However I need to make the first word of secondsToString's result capitalised, like that:

print(secondsToString(10)) // Output is "10 Seconds"
print(secondsToString(1)) // Output is "1 Second"

How can I solve this problem? Should I change some property of DateComponentsFormatter?

Upvotes: 0

Views: 825

Answers (1)

Rakesha Shastri
Rakesha Shastri

Reputation: 11242

Just add .capitalized at the end of your formatted string.

func secondsToString(_ seconds: Int) -> String {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full
    formatter.allowedUnits = [.second]
    return formatter.string(from: DateComponents(second: seconds))?.capitalized ?? ""
}

Note: This solution will capitalize all words that are returned from the method. For your use case this should be good enough, because even if you add more time units, if i were capitalizing one, i would prefer capitalizing all of them.


So, if you were to change the result in some way and want only the first word to be capitalized, you could try this: (First word means first word which contains a letter)

func secondsToString(_ seconds: Int) -> String {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full
    formatter.allowedUnits = [.second, .hour, .day]
    let string = formatter.string(from: DateComponents(second: seconds)) ?? ""
    var substrings = string.components(separatedBy: " ")
    // Using for...each would make the iterating element a constant and hence i would have to find the index and replace it using the index
    for i in 0...substrings.count {     
        if let firstCharacter = substrings[i].unicodeScalars.first, CharacterSet.letters.contains(firstCharacter) {
            substrings[i] = substrings[i].capitalized
            break
        }
    }
    let finalString = substrings.joined(separator: " ")
    return finalString
}

Upvotes: 2

Related Questions