NSFormatters使用

日期和数字是每个App必不可少的一个部分,作为一个合格的app应该能够以合理的格式显示数字,日期等等。由于不通地区,甚至不同场景下所需要的显示格式不一样,格式化这些数据还是比较复杂的。

幸运的是Cocoa框架很擅长于处理相关信息NSFormatter几乎能涵盖所有的转换需求。

iOS8在原来的NSNumberFormatterNSDateFormatter基础上增加了一些新的日期、时间转换以及一些物理量相互转换的方法。

NSNumberFormatter

日常工作中经常需要打印出各类数字,其中很多都是高精度的FloatDouble类型,但是对于我们$10.321 和 $10.321054823并没有多少实质性区别。所以这种时候就需要使用NSNumberFormatter

NSNumberFormatter包含一下几种样式

  • NoStyle
  • DecimalStyle
  • CurrencyStyle
  • PercentStyle
  • ScientificStyle
  • SpellOutStyle

其实这些名字都很好理解,下面就是运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var num = 12345.6789098
let formatter = NSNumberFormatter()
formatter.numberStyle = .NoStyle
var result = formatter.stringFromNumber(num)
//12346

formatter.numberStyle = .DecimalStyle
result = formatter.stringFromNumber(num)
//12,345.679

formatter.numberStyle = .CurrencyStyle
result = formatter.stringFromNumber(num)
//$12,345.68

formatter.numberStyle = .PercentStyle
result = formatter.stringFromNumber(num)
//1,234,568%

formatter.numberStyle = .ScientificStyle
result = formatter.stringFromNumber(num)
//1.23456789098E4

formatter.numberStyle = .SpellOutStyle
result = formatter.stringFromNumber(num)
//twelve thousand three hundred forty-five point six seven eight nine zero nine eight

当然强大的NSNumberFormatter能做的不仅仅是这个,还可以利用以下四个属性指定输出位数

  • var minimumIntegerDigits: Int
  • var maximumIntegerDigits: Int
  • var minimumFractionDigits: Int
  • var maximumFractionDigits: Int
1
2
3
4
5
var num = 12345.6789098
let formatter = NSNumberFormatter()
formatter.maximumFractionDigits = 3
var result = formatter.stringFromNumber(num)
//12345.679

还可以自定义正负数的前后缀

1
2
3
4
5
6
7
var num = 12345.6789098
let formatter = NSNumberFormatter()
formatter.positivePrefix = "正前缀"
formatter.positiveSuffix = "正后缀"
var result = formatter.stringFromNumber(num)
///正前缀12345.679正后缀

更多参数可以通过Command + 点击的方式查看NSNumberFormatter属性来了解。

NSDateFormatter

日期格式化也是个常见需求NSDateFormatter内置一下几种格式

NSDateFormatterStyle Date Out Time Out
ShortStyle 12/25/14 7:00 AM
MediumStyle Dec 25, 2014 7:00:00 AM”
LongStyle December 25, 2014 7:00:00 AM PST
FullStyle Thursday, December 25, 2014 7:00:00 AM Pacific Standard Time

用法

1
2
3
4
5
var date = NSDate(timeIntervalSinceNow: 0)
let formatter = NSDateFormatter()
formatter.dateStyle = .ShortStyle
formatter.timeStyle = .MediumStyle
var result = formatter.stringFromDate(date)

当然除了几种内置格式以外,还可以使用自定义格式,自定义格式比较多,详情参考Getting Started With NSNumberFormatter

新增Formatter

NSDateComponentsFormatter

NSDateComponentsFormatter允许格式化具体的某一向,比如12 days 13 hours and 12 minutes

1
2
3
4
5
6
7
8
9
10
11
12
13
let dateComponentsFormatter = NSDateComponentsFormatter()
let components = NSDateComponents()
components.hour = 2
components.minute = 45

let dcfStyles: [NSDateComponentsFormatterUnitsStyle] =
[.Positional, .Abbreviated, .Short, .Full, .SpellOut]

for style in dcfStyles {
dateComponentsFormatter.unitsStyle = style
dateComponentsFormatter.stringFromDateComponents(components)
}

Units Style Result
.Positional 2:45
.Abbreviated 2h 45m
.Short 2 hrs, 45 mins
.Full 2 hours, 45 minutes
.SpellOut two hours, forty-five minutes

当然还可以重写默认语言,按照指定语言输出

1
2
3
4
5
6
let calendar = NSCalendar.currentCalendar()
calendar.locale = NSLocale(localeIdentifier: "ug")
dateComponentsFormatter.unitsStyle = .Full
dateComponentsFormatter.calendar = calendar
dateComponentsFormatter.stringFromDateComponents(components)
//"2 سائەت and 45 مىنۇت"
NSDateIntervalFormatter
1
2
3
4
5
6
7
8
9
10
let dateIntervalFormatter = NSDateIntervalFormatter()
let now = NSDate()
let longTimeAgo = NSDate(timeIntervalSince1970: 0.0)
let difStyles: [NSDateIntervalFormatterStyle] =
[.NoStyle, .ShortStyle, .MediumStyle, .LongStyle, .FullStyle]
for style in difStyles {
dateIntervalFormatter.dateStyle = style
dateIntervalFormatter.timeStyle = style
dateIntervalFormatter.stringFromDate(longTimeAgo, toDate: now)
}
Style Result
.NoStyle
.ShortStyle 1/1/70, 1:00 AM – 7/30/14, 9:32 AM
.MediumStyle Jan 1, 1970, 1:00:00 AM – Jul 30, 2014, 9:32:35 AM
.LongStyle January 1, 1970, 1:00:00 AM GMT+1 – July 30, 2014, 9:32:35 AM GMT+1
.FullStye Thursday, January 1, 1970, 1:00:00 AM GMT+01:00 – Wednesday, July 30, 2014, 9:32:35 AM British Summer Time
其他

新特性还包括

  • NSLengthFormatter
  • NSMassFormatter
  • NSEnergyFormatter

等,具体的用法可以参考iOS8 Day-by-Day :: Day 15 :: New NSFormatters

应用

下面是我写的简单一个时间格式化函数,把从服务器过去的时间戳与现在时间比较,然后显示恰当的格式。要求如下

与时间时间差 显示
小于60秒 刚刚
1小时 xx分钟前
小于1天 xx小时前
昨天 昨天 xx:xx
一年内时间 xx月xx日 HH:MM
其他显示 xx年xx月xx日 HH:MM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func getTimeString(timeStamp:String) -> String? {
let timeInterval:NSTimeInterval = NSString(string: timeStamp).doubleValue
let time = NSDate().timeIntervalSince1970
if time - timeInterval < 60 {
return "刚刚"
}

var min:Int = Int((time - timeInterval)/60)
if min < 60 {
return "\(min)分钟前"
}

var hour:Int = Int(min/60)
if hour < 24 {
return "\(hour)小时前"
}

let formatter = NSDateFormatter()

if hour < 48 {
formatter.dateFormat = "昨天 HH:MM"
} else if hour < 24 * 365 {
formatter.dateFormat = "M月d日 HH:MM"
} else {
formatter.dateFormat = "yyyy年M月d日 HH:MM"
}

let date = NSDate(timeIntervalSince1970: timeInterval)
let dateStr = formatter.stringFromDate(date)
return dateStr
}

参考