Swift基础库时间小分队
时间问题是任何一个语言都绕不开的领域。
Swift基础库提供了多个类型,他们共同作用解决时间问题。与某些语言只有一两个核心时间类型相比,Swift时间管理相对复杂, 所以我们要理清楚他们之间的相互关系,才能发挥其强大作用。
Swift的时间类型矩阵包括时间表示、历法计算、文本显示(格式化)等,他们的关系是逐级支撑的,如时间表示是基础能力,在此能力之上再通过特定历法把时间转化为人们能够使用的组件,格式化文本进一步转化为可读写的字符串。
时间表示
- Date:表示某个时间点,即一维时间轴上的某个绝对点。是纯粹表达时间的类型,和任何具体的日历、时区或者本地化无关。 需要通过特定Calendar(日历系统)转化为人们能够理解的概念,如2022年1月2日14时2分11秒。
- DateInteval: 用起始时间和结束时间表示的一个时间跨度: [起始时间Date,结束时间Date]是一个封闭的周期。 结束时间可以等于或者晚于起始时间,但不能早于起始时间。这个类型是对Date表示一个时间点的补充,它表现出了一个时间跨度。
- TimeInterval: 用秒表示的时间间隔,Double类型。
注意,swift中的Date表达的是我们日常中所说的时间概念。 Swift基础库中并没有Time这一类型。
Date表示一个独立于任何历法系统的时间点, DateInterval表示一个被起始时间和结束时间规定的时间跨度,TimeInterval是以秒为单位的一个数值,表示时间跨度的大小。这三个概念合起来,在没有任何历法系统的基础上可以表示任何时间的点(点)、始终跨度(线段)和长度(长度)。
历法计算
- Calendar:日历系统,把时间点转化为人们容易理解、方便记忆和交流的表达系统,以及反向的转化。
- DateComponents: 时间组件,把时间的组件氛围年月日时分秒,并用Calendar系统转化为具体的时间。
- TimeZone: 定义了在不同时区之间进行时间转化的行为规则。 主要包括指定时区于格林威治标准时间的偏移量,以及时区特定的英文缩写和识别符。
Swift使用Calendar、DateComponents和TimeZone三种类型,把物理上的时间概念和人们日常使用的历法系统及时区对应起来。这三个类型可以比作密码破译机器,将不可读的Date等类型,翻译成人们能够理解的日期和时间概念。
人们理解和使用时间,必须通过使用历法系统。swift使用Calendar类型来处理历法。Calendar通过不同的识别符创建,我们最常用的如gregorian代表公历,chinese代表中国农历等。 也可以通过current/autoupdatingCurrent方法来获取当前系统使用的历法。
Calendar的拆解组件功能可以从时间或者时间周期拆解出相应的历法组件(年月日时分秒等)。相关的成员函数有component (拆解出单个组件)和dateComponents(针对时间点或者时间跨度拆解出多个组件),也可以比较一个Date和一个DateComponents是否符合。
反过来,Calendar的组装时间功能可以从提供的时间组件中计算出对应的时间点,这是由一系列的date成员函数提供的。 其中包括设置某些组件或在组件基础上增加数值的不同途径获取新时刻。
Calendar提供了计算时间跨度的功能。如提供某一个时间点针对特定时间组件的时间跨度(通过DateInterval或inout参数返回),以及特定周末的时间跨度等。 这些函数很多包含dateInterval字串。
Calendar的扫描时间功能提供了重复枚举时间组件(及组合)的功能,如重复每天或每小时,在符合重复条件时可调用closure的功能。 Calendar提供了计算某个时间所在天的最早时刻功能。
Calendar提供了时间比较功能。 时间比较时基于提供的粒度属性,提供了知道此粒度的比较结果。例如,粒度组件参数设置为小时,则比较从最大的时间组件向下比较到小时结束,不往下进行。 此功能模块还提供了两个时间点是否在一天、某个时间点是否在今天、昨天、明天或者周末的能力。
Calendar还提供了其他琐碎功能,如比较两个日历系统是否一致、获取上下午、星期、月、季、公元等符号。
可以通过属性直接获取的Calendar信息包括标识字符串、时区、区域设置、周起始日、第一周最少天数、时间组件的最大和最小范围、某个时间点较小时间组件在较大时间组件的序数和范围等。
DateComponents的初始化比较难理解的一点是如果某一组件或者calendar、timeZone没有给初始值(默认为nil),那它对应的时间是怎么计算的。 又或者如果某两个组件数值相互冲突,如日期和周几的数值不一致,是如何处理的。 结论是calendar参数是必须要提供的,否则其他函数都不能返回有效值。在有calendar参数的情况下,其他参数缺失也能提供默认值为0或者1, 从而可以返回有效的date;即使参数冲突、或者参过限度,时间是否合法的判断函数返回false,其他获取组件的函数仍然能够工作,甚至能否返回对应的date。
DateComponents同时提供了访问和设置各个子属性值的方法。
TimeZone可以通过current和autoupdatingCurrent两个方法获取当前系统的时区,后一种会跟随系统设置的变化自动调整。
TimeZone的初始化可以通过识别符、缩写,或者与GMT的秒差创建。 TimeZone提供了类型函数来列举所有已知的识别符和缩写字典。
TimeZone提供了对识别符、缩写、和GMT的秒差等信息,及对夏令时的一些操作。
格式化文本
- DateFormatter:时间的格式化,提供了时刻Date和它的文本表示之间的对应和转换。
- DateComponentsFormatter: 时间组件的格式化。
- DateIntervalFormatter:时间间隔的格式化。
- ISO8601DateFormatter: 基于8601国际标准的时间格式化。
DateFormatter提供了字符串和时间时间的互相转换。
可以通过两种方法设置时间表达字符串的格式,一个是通过dateStyle和timeStyle属性;另外一种方法是通过fixed的方法,dateFormat输入格式字串。
DateFormater可以操作的属性包括: 历法系统、 区域设置、时区、两位数字的起始时间、公历起始时间等等,以及获取上下午、星期、月和季度的表示符号等。
时间组件的文本表示通过DateComponentsFormatter完成。 此类的方法不仅有把时间转化为字符串的方法,还另外包括将时间跨度格式为字符串。
DateIntervalFormatter是对时间跨度进行格式化的类型。
ISO8601Formatter是基于国际标准的日期和时间与文本相互转化工具。
Locale区域设置中,有关于时间的部分,包括时间的文本显示、时区、历法、周首日等。