如何在iPhone上本地化“定时器”

9
我需要在iPhone上以“hh:mm:ss”格式显示计时器,但希望本地化。例如,芬兰使用时间组件之间的句点而不是冒号(hh.mm.ss)。如果我处理的是“时间”,苹果的NSDateFormatter就可以解决问题,但我需要显示远大于24小时的小时数。
我无法使NSDate/NSDateFormatter正常工作,因为当您使用秒钟创建一个NSDate对象时...
NSDate *aDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTotalSeconds];

每经过86400秒(一天),NSDate会自动将日期增加一天,而小时、分钟和秒则归零。我需要让它在任意秒数上工作而不会翻转。例如,使用86401秒,我想要显示24:00:01(或者在芬兰显示为24.00.01)。

我的代码可以正确处理总秒数,所以唯一的问题是显示。一个简单的...

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

如果我能找到一种获取本地化的“sepString”(时间分量分隔符)的方法,那么这个方法就会起作用。NSLocale似乎没有提供这个功能。你有什么想法吗?

我不确定我理解问题,但你是否在寻找分组分隔符?它的键是NSLocaleGroupingSeparator。请参阅此处的NSLocale文档:http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html - Justin
@Justin:我认为组合分隔符是千位之间的标点符号,例如在美式英语中,123,456,789 中的逗号。 - Daniel Dickison
5个回答

4
以下是关于世界各地使用何种字符来分隔时间组件的信息,供其他人参考。我查看了我的iPhone-iOS版本4.1(8B117)上的所有“区域格式”设置,并发现除了七个地区外,所有地区都使用冒号(hh:mm)。以下是其他地区(它们的NSLocaleCountryCode用花括号括起来):

使用句点,hh.mm

• 丹麦语(丹麦){DK}
• 芬兰语(芬兰){FI}
• 塞尔维亚黑山(西里尔文){ME}
• 塞尔维亚黑山(拉丁文){ME}
• 塞尔维亚语(西里尔文){RS}
• 塞尔维亚语(拉丁文){RS}

使用破折号,hh-mm

• 马拉地语(印度){IN}

请注意,印度(而不是马拉地-印度)也有国家代码IN,并且使用冒号。因此,仅检查国家代码是不够的,您还需要查看其他NSLocale字段。我还没有查看所有字段,但我怀疑NSLocaleScriptCode或NSLocaleVariantCode可能会使它们有所不同。这种复杂性是苹果应该在SDK中向我们公开此字符的原因。我已经在Radar中记录了它,因此如果您同意,请也提出请求,请求的数量在他们决定要做什么方面非常重要。

3

这里有一个相当hackish的方法,可以获取任何语言环境下的时间分隔符。它适用于iOS 3.2及以上版本。我知道代码可以更简洁,但我打开了我的“最大冗长性”标志,以使其尽可能易读。

//------------------------------------------------------------------------------
- (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];
}
//------------------------------------------------------------------------------

2

iOS8及以后版本可以使用DateComponentsFormatter。以下是Swift 3的示例。

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)

0
首先,您应该使用NSDateFormatter来格式化您的日期。Apple建议使用内置样式,用户可以在设置中进行自定义。下面的代码直接来自苹果文档:
 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);

3
明白了,但我并没有显示日期,也没有显示时间(0:00到23:59)。我正在显示小时、分钟和秒。简单来说,如果计时器运行了2天3小时4分钟5秒,我想显示51:04:05,并使用用户所在地区惯用的格式。我想我会将时间分隔符硬编码为冒号,并完成它,然后向苹果提出功能请求以获取所在地区的时间组件分隔符。 - Swany
抱歉,应该更仔细地阅读问题!快速浏览文档后,我没有找到直接本地化TimeIntervals的方法。假设DateFormatter使用正确的分隔符,您可以使用它来查找本地环境的分隔符应该是什么。 这有点可怕,但至少可以解决iPhone上的本地化设置。 - brain
1
那是一个好主意,谢谢。我检查了一下,在iOS中NSDateFormatter确实会正确地使用区域设置(地区),因此我可以从其中获取字符。我认为使用NSDateFormatterShortStyle并解析返回的字符串以获取第一个非数字字符可能是最安全的方法来进行此“黑客”操作。即使苹果公司在SDK中添加了获取时间组件分隔符的方式,该方式只适用于最新版本,而我仍然需要解决早期iOS版本的问题。 - Swany

0
如果其他方法都失败了,考虑使用 NSLocalizedString() 或 NSLocalizedStringWithDefaultValue。

同意,NSLocalizedString 无法解决这个问题。有趣的是,苹果时钟应用程序中的计时器功能不会更改分隔符以匹配地区设置。 - Swany
这是正确的方法。在您的Localizable.strings文件中创建一个字符串格式,然后为每种语言创建一个版本的格式字符串。使用NSLocalizedString()获取用户当前语言的正确版本的格式字符串,并将该格式字符串作为第一个参数传递给+[NSString stringWithFormat:]。这样您就可以始终获得所需的格式。 - Ryan
1
你不能使用NSLocalizedString来做这件事。在iPhone上,它只适用于语言(而不是区域设置)。日期格式差异与语言无关,而与区域设置有关。语言是英语(en)、法语(fr)等,而区域设置是美国(US)、英国(GB)等。由于某种原因,“en-GB”中的字符串在iPhone上无法工作。即使它能够工作,也有超过240个区域设置需要支持。这就是为什么苹果发明了NSLocale,我只是想看看是否有遗漏的地方,或者确实没有办法获取区域设置的时间组件分隔符。 - Swany
你有看过NSDateFormatter吗? - joshpaul
可以,但是它无法显示大于23的小时数(请参见最初的问题)。 - Swany
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接