DateFormatter

最近遇到一个问题。一个关于时间的 UI 显示,需要显示上午/下午。一般来说,就是在 DateFormatter 里面进行设置 dateFormat 即可。但是一般都是AM/PM。后来发现 iOS/macOS 比较都可以显示上午/下午的。苹果的开发团队不可能还傻到得自己去算时间吧。于是看 DateFormmatter 的文档,发现了 Locale 这个东西。

说了这么多废话。总算进主题了。该篇是整理下 DateFormatter。老司机就不用往下看了。😂。

DateFormatter 使用

DateFormatter 的使用比较简单。一般的话,很常见的用法就是用 DateFormatter 将 Date 和 String 互换。看🌰。

1
2
3
4
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY年MM月dd日 HH:mm:ss"
dateFormatter.string(from: date)

dateFormat的格式,其实是遵守Unicode Technical Standard

To specify a custom fixed format for a date formatter, you use setDateFormat:. The format string uses the format patterns from the Unicode Technical Standard #35. The version of the standard varies with release of the operating system:

OS X v10.9 and iOS 7 use version tr35-31.

OS X v10.8 and iOS 6 use version tr35-25.

不同系统版本遵循的格式范围不同。不过现在普遍都是 iOS 7 以上适配了。

在 Unicode Technical Standard 中,Date Format Patterns支持的格式挺多的。这里只列一些常用的。

Field symbol Description
年份 y 正常的年份显示,可以用多种组合。
U 表示农历年份,干支纪法。比如 甲子、丁酉。但是需要配合CalendarLocale使用
月份 M 表示 monthSymbols。 M/MM表示月份的数字,如 1/01;MMM表示简写月份,对应着shortMonthSymbols,如 Jun;MMMM表示标准月份,对应着monthSymbols,如 June;MMMMM表示最简的月份表示,对应着veryShortMonthSymbols,如一月份是 J
L 表示 standaloneMonthSymbols。类同 M 的表示方法。
天数 d 表示一个月中的第几天,d/dd表示 1/01 的区别
D 表示一年中的第几天,可D/DD/DDD
w 表示一年中的第几周,可w/ww
W 表示一个月中的第几周,可W
E 表示周几这样。比如星期日。E\EE\EEE->Sun, EEEE->Sunday, EEEEE->S。还可以搭配 Calendar 和 Locale,显示中文的 周日/星期日/日
c 同 E。但是主要是是对应standaloneWeekday。搭配组合规则同 E
时钟 h 12小时制。可h/hh
H 24小时制。可H/HH
分钟 m 分数。可m/mm
秒钟 s 秒数。可s/ss

常用的一些组合,大概是以上这些。按照Unicode Date Format的话,其实还有季度、毫秒级的一些表示。

比如今日是 2018年1月16日。那么通过 DateFormatter 表示农历日期,可以是

1
2
3
4
5
6
7
8
9
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY年MM月dd日 HH:mm:ss"
dateFormatter.string(from: date)
dateFormatter.locale = Locale(identifier: "zh_CN")
dateFormatter.calendar = Calendar(identifier: .chinese)
dateFormatter.dateStyle = .medium
dateFormatter.dateFormat = "U年MMMd EEE a"
dateFormatter.string(from: date) // 丁酉年冬月三十 周二 下午

其中,可以针对 DateFormatter 的 monthSymbols 等一些属性,设置我们特有的一些表示习惯。比如,一月我们希望显示是正月,而冬月和腊月则显示十一月、十二月。那么可以通过这样进行设置。

1
2
3
4
5
6
7
8
9
10
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY年MM月dd日 HH:mm:ss"
dateFormatter.string(from: date)
dateFormatter.locale = Locale(identifier: "zh_CN")
dateFormatter.calendar = Calendar(identifier: .chinese)
dateFormatter.dateStyle = .medium
dateFormatter.shortMonthSymbols = ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
dateFormatter.dateFormat = "U年MMMd EEE a"
dateFormatter.string(from: date) // 丁酉年十一月三十 周二 下午

大概就这些了吧。

参考

Date and Time Programming Guide

Unicode Technical Standard

Date Format Patterns