How To Localize a “Timer” on iPhone

I need to display a timer in “hh:mm:ss” format on the iPhone, but want it localized. Finland, for example uses a period instead of a colon between the time components (hh.mm.ss). Apple’s NSDateFormatter would do the trick if I was dealing with a “time” but I need to display hours much greater than 24.

I have not been able to make an NSDate/NSDateFormatter work because when you make one with seconds…

  • iOS-Charts Float to Integer YAxis
  • iOS 3DES encryption for TPV payments
  • SpriteKit move rotated physicsBody with applyImpulse
  • How to delete an app which is waiting for upload?
  • RestKit: mapping JSON array of strings
  • Read iPhone Settings Programmatically (Precisely Settings->General->Date & Time->Set Automatically)
  • NSDate *aDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTotalSeconds];
    

    … every 86,400 seconds (one day’s worth) NSDate automatically increments the day and hours, minutes, and seconds go back to zero. I need to make it work on an any number of seconds without rolling over. For example, with 86,401 seconds I want to display 24:00:01 (or 24.00.01 in Finland).

    My code manages total seconds fine, so the only problem I have is the display. A simple…

    [NSString stringWithFormat:@"%d%@%d%@%d", hours, sepString, mins, sepString, secs]
    

    … would work if I could find a way to get at a localized “sepString” (the time component separator). NSLocale does not seem to have this.

    Thoughts?

    5 Solutions Collect From Internet About “How To Localize a “Timer” on iPhone”

    Here is a admittedly hackish way to get the time component separator for any locale. It should work on iOS 3.2 and above. I know the code can be more concise, but I turned my “maximum-verbosity” flag on to make it as readable as possible.

    //------------------------------------------------------------------------------
    - (NSString*)timeComponentSeparator
    {
        // Make a sample date (one day, one minute, two seconds)
        NSDate *aDate = [NSDate dateWithTimeIntervalSinceReferenceDate:((24*60*60)+62)];
    
        // Get the localized time string
        NSDateFormatter *aFormatter = [[NSDateFormatter alloc] init];
        [aFormatter setDateStyle:NSDateFormatterNoStyle];
        [aFormatter setTimeStyle:NSDateFormatterShortStyle];
        NSString *aTimeString = [aFormatter stringFromDate:aDate]; // Not using +localizedStringFromDate... because it is iOS 4.0+
    
        // Get time component separator
        NSCharacterSet *aCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@":-."];
        NSRange aRange = [aTimeString rangeOfCharacterFromSet:aCharacterSet];
        NSString *aTimeComponentSeparator = [aTimeString substringWithRange:aRange];    
    
        // Failsafe
        if ([aTimeComponentSeparator length] != 1)
        {
            aTimeComponentSeparator = @":";
        }
    
        return [[aTimeComponentSeparator copy] autorelease];
    }
    //------------------------------------------------------------------------------
    

    Here is information on this topic for others who might be trying to figure out what character different areas of the world use to separate time components. I went through all of the “Region Format” settings on my iPhone – iOS version 4.1 (8B117) and I found all but seven regions use a colon (hh:mm). Here are the others (their NSLocaleCountryCode is in curly braces).

    Use a period, hh.mm

    • Danish (Denmark) {DK}
    • Finnish (Finland) {FI}
    • Serbian Montenegro (Cyrillic) {ME}
    • Serbian Montenegro (Latin) {ME}
    • Serbian (Cyrillic) {RS}
    • Serbian (Latin) {RS}

    Use a dash, hh-mm

    • Marathi (India) {IN}

    Note that India (not Marathi-India) also has the country code IN and it uses a colon. So just checking the country code is not enough, you will have to look at other NSLocale fields. I haven’t gone through all the fields yet, but I suspect NSLocaleScriptCode or NSLocaleVariantCode might differentiate them. This complexity is why Apple should expose this character to us in the SDK. I did log it in Radar, so if you agree please request it too, quantity of requests matters a lot in what they decide to do.

    If all else fails, look at using NSLocalizedString() or NSLocalizedStringWithDefaultValue.

    First of all you should be using NSDateFormatter to format your dates. Apple recommends using the built-in styles available that the user can customize in the settings. The following code is straight from the apple docs:

     NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
    
    NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:118800];
    
    NSString *formattedDateString = [dateFormatter stringFromDate:date];
    
    NSLog(@"formattedDateString for locale %@: %@",
    
            [[dateFormatter locale] localeIdentifier], formattedDateString);
    

    In iOS8 and newer you can use DateComponentsFormatter. Below is a Swift 3 example.

    let duration: NSTimeInterval = 86401 // 24:00:01
    
    let formatter = DateComponentsFormatter()  
    formatter.unitsStyle = .positional  
    formatter.allowedUnits = [.hour, .minute, .second]  
    formatter.zeroFormattingBehavior = [.pad]
    
    let formattedDuration = formatter.string(from: duration)