##SwiftDare 中文版说明文档 - 修改时间 - 5 @(丁香园学习笔记)[swift, 翻译]
使用 SwiftDate 来对时间进行相关修改操作十分简便;修改时间组件,比较两个时间(时间的不同以他们之间的不等组件来表示)。无论是带有地区属性的 DateInRegion
时间实例还是单一结构的 Date
时间实例,都可以进行这些操作。
为时间添加组件
你可以使用 Swift 中常用数学运算符,来增减时间元素的值。如+
、-
根据你所表达的上下文,SwiftDate 会自动判断并生成带有地区属性的 DateInRegion
时间实例或单一结构的 Date
时间实例。
可用的时间组件有: nanoseconds
,seconds
, minutes
, hours
, days
, weeks
, years
下面是一些数学运算的例子:
// 创建一个罗马时间 2015-01-03 @ 15:10:00
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
var date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
// 让我试试数学运算符修改时间元素值
date = date + 3.seconds + 15.minutes // -> 03 gen 2015, 15:25:03 CET
date = date - 120.seconds // minus 2 minutes -> 03 gen 2015, 15:23:03 CET
date = date + 3.weeks // 24 gen 2015, 15:23:03 CET
// 你也可以直接增加绝对秒数,SwiftDate 会自动帮你换算
date.add(interval: 10) // 24 gen 2015, 15:23:03 CET
###比较时间 --- **概述** 在 Swift3 的 Foundation 库中,已经支持比较 `Date` 时间实例。 SwiftDate 为带有地区属性的 `DateInRegion` 补充了相似的比较方法,并通过添加新方法扩充了现有 Foundation 库对不同粒度下的时间比较。
比较简单时间
你可以使用 >
,>=
, <
, =<
运算符来比较时间,例如:
// 03 gen 2015, 15:10:00 CET
let date1 = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
let date2 = try! DateInRegion(components: [.year: 2015, .month: 2, .day: 5, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
if date2 > date1 { // DateInRegion supports Equatable protocol you can use >=, <=, < or >
print("'\(date2)' date is later than '\(date1)'")
}
if date2 == date1 {
// simple equality
}
###时间所对应的单位起始值 --- **概述** 利用 `.startOf()` 方法,传入计算单位后,你可以获得改时间到现在的差值。补充说明:时间是一个点值,而时间的单位都是一段时间的差值,这里的起始值指的就是时间点值在时间单位的区间中的左边界值;比如,2016-11-11 20:39:50 ,以月为单位,起始值是 2016-11-01 00:00:00;以小时为单位 ,起始值是 2016-11-11 20:00:00。 **声明** `startOf(component: Calendar.Component) -> DateInRegion` `startOf(component: Calendar.Component) -> Date`
参数
component
: component to alter
返回值
返回给定时间单位区间的起始值所对应的 DateInRegion
/Date
时间实例。
例子
// Create a Region in Rome TimeZone with Gregorian Calendar and Italy locale settings
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
// 03 gen 2015, 15:10:00 CET
let date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
let startOfHour = date.startOf(component: .hour) // 03 gen 2015, 15:00:00 CET
let startOfMonth = date.startOf(component: .month) // 01 gen 2015, 00:00:00 CET
let startOfWeek = date.startOf(component: .weekOfMonth) // 28 dic 2014, 00:00:00 CET
###时间所对应的单位结束值
概述
利用 .startOf()
方法,传入单位后,你可以获得现有时间对应的结束址。
声明
endOf(component: Calendar.Component) -> DateInRegion
endOf(component: Calendar.Component) -> Date
参数
component
: component to alter
返回结果
返回给定时间单位区间的结束址所对应的 DateInRegion
/Date
时间实例。
// Create a Region in Rome TimeZone with Gregorian Calendar and Italy locale settings
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
// 03 gen 2015, 15:10:00 CET
let date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
let startOfHour = date.endOf(component: .hour) // 03 gen 2015, 15:59:59 CET
let startOfMonth = date.endOf(component: .month) // 31 gen 2015, 23:59:59 CET
let startOfWeek = date.endOf(component: .weekOfMonth) // 03 gen 2015, 23:59:59 CET
###对时间的时刻进行修改
概述
针对现有的时间实例, .atTime(hour:minute:second)
方法可以修改时刻,提供 时
、分
、 秒
的值,获得一个新的时间,新的实例中日期与日期不变。
异常
如果原时间不能生成新时间,会抛出 .FailedToCalculate
异常。
声明
func atTime(hour: Int, minute: Int, second: Int) throws -> DateInRegion
func atTime(hour: Int, minute: Int, second: Int) throws -> Date
参数
hour
: hour(s) to setminute
: minute(s) to setsecond
: second(s) to set
返回结果
在原时间基础上,依据你提供的时
、分
、秒
生成一个新时间实例,地区设置保持不变。此外,其他的时间组件在必要时 SwiftDate 会加以修改,以保持合理性。
例子
// 生成一个新的罗马时间,日历格式选择公历,时间表述格式以意大利为准。
// 03 gen 2015, 15:10:00 CET
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
let date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
// 应用 `.atTime()` 方法
let newDateAtGivenTime = try! date.atTime(hour: 09, minute: 10, second: 22) // 03 gen 2015, 09:10:22 CET
###对时间的指定组件进行修改 概述 对指定的时间组件的值进行修改,在保证其他组件值合理的情况下,返回一个新的时间实例。
声明
func at(unit: Calendar.Component, value: Int) throws -> DateInRegion
func at(unit: Calendar.Component, value: Int) throws -> Date
参数
unit
: calendar component unit to alter
异常
如果给定的组件赋值不成功,不能生成新时间实例时,会抛出 .FailedToCalculate
异常。
返回结果
在原时间基础上,修改给定组件的值,然后生成新的时间实例并返回。SwiftDate 在合理的前提下不会改变与给定组件相比单位更大组件的值。补充说明:如果修改了时间中 日
的值,那所有的时
、分
、秒
等更小的组件的值都会被赋最小值 ,而 年
月
等更大单位的组件的值会保持原样,这样做是为了保持合理性,03-31,如果对月改成 2 ,那2-31 很明显不合理。比如 2016-11-11 11:11:11 修改了 月
为 12
那,返回的新的时间是 2016-12-01 00:00:00
例子
// 生成一个新的罗马时间,日历格式选择公历,时间表述格式以意大利为准。
// 03 gen 2015, 15:10:00 CET
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
let date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
let atGivenYear = try! date.at(unit: .year, value: 2020) // 01 gen 2020, 00:00:00 CET. day is altered
###批量修改时间组件的值 --- **概述** 给定一个 `[时间组件 : 值]` 的字典,SwiftDate 会根据时间组件的单位由小到大排序,并修改对应组件的值。 在 SwiftDate 中,规定时间组件的由小到大排序为: `.nanosecond`,` .second`,` .minute`,` .hour`,` .day`,` .month`,` .year`,` .yearForWeekOfYear`,` .weekOfYear`,` .weekday`,` .quarter`,` .weekdayOrdinal`,` .weekOfMonth`.
声明
func at(unitsWithValues dict: [Calendar.Component : Int]) throws -> DateInRegion
func at(unitsWithValues dict: [Calendar.Component : Int]) throws -> Date
参数
unitsWithValues
: calendar component units to alter
异常
对某些时间组件赋值发生错误时,会抛出 .FailedToCalculate
异常。
返回结果 对指定组件赋值后,生成一个新的时间实例,比给定时间组件更大的组件将不会被修改,更小的如果没有赋值将全部赋最小值;这部分的原理,在上一个方法中有补充说明。
例子
// Create a Region in Rome TimeZone with Gregorian Calendar and Italy locale settings
// 03 gen 2015, 15:10:00 CET
let regionRome = Region(tz: TimeZoneName.europeRome, cal: CalendarName.gregorian, loc: LocaleName.italianItaly)
let date = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
let time = try! date.at(unitsWithValues: [.year: 2016, .month: 7]) // 01 gen 2016, 00:00:00 CET
###获取多个时间中的最靠前(时间线上最靠右的)的时间 **概述** 在给定的多个时间实例集合中,返回其中最新的时间实例。比较依据绝对时间值,时间实例的地区,时区,表述格式等组件不会对比较结果产生影响。
声明
(DateInRegion) static func latestDate(_ list: [DateInRegion]) -> DateInRegion
(Date) static func latestDate(_ list: [DateInRegion]) -> Date
例子
// date1 = 2015-01-03 15:10:00
let date1 = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
// date2 = 2014-12-30 20:10:00
let date2 = try! DateInRegion(components: [.year: 2014, .month: 12, .day: 30, .hour: 20, .minute: 10, .second: 0], fromRegion: regionRome)
// date3 = 2015-01-03 15:20:00
let date3 = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 20, .second: 0], fromRegion: regionRome)
// get the latest date in a set
let latestDate = DateInRegion.latestDate([date1,date2,date3]) // is date1 (2015-01-03 14:20:00 +0000)
// or directly via Array extension
let latestDate = [date1,date2,date3].latestDate
###获取多个时间中最久远(时间线上最靠左的)的时间 **概述** 在给定的多个时间实例集合中,返回其中最久远的时间。比较依据绝对时间值,时间实例的地区,时区,表述格式等组件不会对比较结果产生影响。
声明
(DateInRegion) static func earliestDate(_ list: [DateInRegion]) -> DateInRegion
(Date) static func earliestDate(_ list: [DateInRegion]) -> Date
例子
// date1 = 2015-01-03 15:10:00
let date1 = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 10, .second: 0], fromRegion: regionRome)
// date2 = 2014-12-30 20:10:00
let date2 = try! DateInRegion(components: [.year: 2014, .month: 12, .day: 30, .hour: 20, .minute: 10, .second: 0], fromRegion: regionRome)
// date3 = 2015-01-03 15:20:00
let date3 = try! DateInRegion(components: [.year: 2015, .month: 1, .day: 3, .hour: 15, .minute: 20, .second: 0], fromRegion: regionRome)
// get the latest date in a set
let earliestDate = DateInRegion.earliestDate([date1,date2,date3]) // is date2 30 dic 2014, 20:10:00 CET
// or directly via Array extension
let earliestDate = [date1,date2,date3].earliestDate
###给定单位,比较两时间实例 **概述** 在给定单位的前提下,比较现有时间是否晚于提供的时间。
声明
func compare(to date: DateInRegion, granularity: Calendar.Component) -> ComparisonResult
func compare(to date: Date, granularity: Calendar.Component) -> ComparisonResult
参数
date
: date to comparegranularity
: 你所期望的比较粒度至少要比两时间之间的最大不同组件之间要小,否则比较结果会显示相等。 补充说明 在同一个月的两个不同时间时间,以月
为单位比较时,是相等的,比如(伪代码)date1 = 2016-11-11 11:11:11
date2 = 2016-11-12 11:11:11
但日
或者更小的的单位比较,返回结果就是date2
更大
###是否早于某时间(给定单位) 概述 在给定单位前提下,比较现有时间是否早于给定时间。
声明
func isBefore(date: DateInRegion, orEqual: Bool = false, granularity: Calendar.Component) -> Bool
func isBefore(date: Date, orEqual: Bool = false, granularity: Calendar.Component) -> Bool
参数
date
: date to compareorEqual
: true to also check for equalitygranularity
: The smallest unit that must, along with all larger units, be less for the given dates.
###是否晚于某时间(给定单位) **概述** 在给定单位粒度前提下,比较现有时间是否晚于给定时间。
声明
func isAfter(date: DateInRegion, orEqual: Bool = false, granularity: Calendar.Component) -> Bool
func compare(to date: Date, granularity: Calendar.Component) -> ComparisonResult
func isAfter(date: Date, orEqual: Bool = false, granularity: Calendar.Component) -> Bool
参数
date
: date to compareorEqual
: true to also check for equalitygranularity
: The smallest unit that must, along with all larger units, be less for the given dates.
###是否等于某时间 **概述** 比较现有时间实例是否完全等于给定时间。
声明
func isEqual(to compareDate: DateInRegion) -> Bool
参数
compareDate
: a date to compare against