如果有人问我项目中最常用的东西是什么,我会告诉他:日期处理。毫无疑问,不管项目和“日期”有何关系,开发人员都需要和 NSDate 对象打交道。无论是把日期对象
转换成可读字符串,还是使用日期对象进行某种计算,都需要了解这方面的编程知识。日期编程很容易掌握,而且可以帮助你在其他重要的任务中有所收获。对编程新手来说处理日期是个麻烦事,实际上,只要你掌握要领,就得心应手。

在程序中使用 NSDate ,最常见的操作是将其转换成字符串对象,这样就可以很方便的进行格式化,供用户查看。另外,就是逆操作:将字符串对象转换成日期对象。但是,这些并不是所有关于日期的操作,以下是一些例子:

日期比较
给定一个日期(比如当前日期),计算某个时间段(比如某天、某月或某年)之后或之前的日期
计算日期差值(给定两个日期,计算间隔)
将日期对象拆分开,并访问不同的部分(年,月等)
所有上面的操作,包含字符串和日期之间的互相转换,是本教程的讨论对象。接下来的部分,你将看到这些操作都是十分简单的——关键是了解工具和使用方法。

nsdate-featured.jpg

下面,我列出了一些关键文档的链接供你参考。请先进行查看以便获取必要的信息:

NSDate
NSDateFormatter
NSDateComponents
NSDateComponentFormatter
NSCalendar
关于Demo App
在本教程中我们不会真正操作一个 demo 程序,而是会利用 Playground 来展示所有示例。选择这种方式是因为我想要提供给你关于 NSDate 类各种使用的代码片段。
尽管如此,你还是通过这个链接下载 playground 文件,并用 Xcode 打开。这里我强烈建议你创建一个新的 Playground 文件,亲自测试接下来提供的所有代码片段。这将帮助你更好的理解每个示例是如何工作的,另外,修改其中的代码,你将更直观的看到结果是如何改变的。
我提供的 playground 文件叫 PlayingWithDates ,你可以使用同样的名字创建,也可以自己改一个。

基础知识

在我们开始详细学习日期处理之前,需要先搞懂一些基础概念。那就从最简单的 NSDate 对象开始吧,在日期编程中,这个对象描述了 日期 和 时间 信息。所以它不但用于日期,也用于时间处理。格式化 这个概念在直接处理 NSDate 对象时还用不到。可以把日期和时间看做是类中普通的属性。只有在将日期对象转换为字符串对象时,才能用到格式化,接下来我们会看到许多格式化的实例。简单说来,不论你需要的是日期、时间,或者两者都需要,NSDate 类都可以胜任。

另外一个稍后需要关注的类是 NSDateComponents 。这个类可以简单的看做是 NSDate 的“姐妹”类,因为它为开发者带来了许多关于日期的便捷操作。其中一项重要内容是:它可以将日期和时间分割成独立的属性,这样就可以直接访问每项属性,这在诸如日期计算之类的任务中非常有用。例如:NSDateComponents 实例中的“天”和“月”就可以按照如下方式展现:

let dateComponents = NSDateComponents()
let day = dateComponents.day
let month = dateComponents.month
这很简单。另外,访问日期组件(年,月,日等)并生成日期属性到 NSDateComponents 中去需要先执行一些转换命令,我们接下来会谈这个。除了上面这些功能外, NSDateComponents 类在计算过去或未来的时间上也很有用。只需要简单的对某个子属性(年,月年等)执行加减操作,就可以算出未来或过去的一个时间。另外,NSDateComponents 类还适合查找两个日期之间的间隔。后面我们会详细的说明。

我们暂时不会详细学习 NSDateComponents 类,这里我们只需要学一下如何将 NSDate 和 NSDateComponents 对象互相转换,要提到的另外一个重要角色是 NSCalendar 类。这个类的功能并不在本文的讨论范围,但是,NSDate 和 NSDateComponents 之间的互相转换,却是有 NSCalendar 类来控制的(因为需要制定某个 NSCalendar 对象,才能完成转换)。事实上,系统在进行转换时,需要知道使用的日历(历法)是哪个,然后才能获得正确的转换结果(要知道,世界上有许多不同的日历,其年月日的值是各不相同的)。你可以通过介绍中的文档链接查看关于calendar的详情,在这里,你只需要知道我们会用 NSCalendar 的 currentCalendar() 方法获取系统当前的calendar即可。

除了上述工具外,还有一个重要的 NSDateFormatter 类需要了解。这个类会帮助我们将 NSDate 对象转换为字符串对象,也可以将字符串对象转换为 NSDate 对象。通过它,可以将 NSDate 对象按照预定义的日期样式直接转换成字符串,也可以按自定义的日期格式进行转换。我们稍后会看到几个这样的实例,也会看到互相转换的例子。 NSDateFormatter 对象也支持本地化功能,只需要提供一个有效的 NSLocale 对象,就可以按照给定的locale设置转换成合适的字符串内容。

另外一个类似的类是 NSDateComponentsFormatter ,它有一个重要目的:输入日期和时间,输出格式化好的可读字符串。它包含了许多方法来完成这个任务,在本教程最后部分你将看到几个这样的例子。但是在本教程中,除了例子中涉及的内容外,我们不会过多的讲解这个类。

接下来,我们将直接学习之前提到的工作时如何完成的。再次建议你新建一个 playground 文件,最好的学习方法就是自己亲身实践。

NSDate和字符串相互转换

一开始,我们需要通过 NSDate 类获取当前日期,并且将其赋值给一个常量。和其他语言不同,获取当前时间并不需要如 Now() 或者 today() 之类特别的方法,只需要初始化一个 NSDate 对象即可。

1
let currentDate = NSDate()
在Xcode playground中写入代码后,结果如下:

t44_1_current_date.png

注意:这个值我们在后面会多次用到。现在来初始化一个 NSDateFormatter 对象,它是我们用来转换日期和字符串的工具。

1
let dateFormatter = NSDateFormatter()
dateFormatter 对象默认会使用系统中设置的区域信息,除非显式地设置区域。即便如此,手动设置区域也不是必须的。以下是设置区域的代码:

1
dateFormatter.locale = NSLocale.currentLocale()
设置其他区域也很简单,只需要通过 区域代码 匹配到对应的区域即可。

1
2
dateFormatter.locale = NSLocale(localeIdentifier: “el_GR”)
dateFormatter.locale = NSLocale(localeIdentifier: “fr_FR”)
这两行代码展示了如何设置不同的区域,这里用的是希腊和法国。当然,这样依次设置多个区域是没有意义的,因为只有最后一次设置会生效。想知道区域信息对日期转换字符串有什么影响吗?马上你就会看到。

使用date formatter style格式化输出字符串
在将 NSDate 转换成字符串之前,你需要先“告诉”date formatter你想要什么样式的字符串。有两种方式可以设置格式:一种是通过一些预定义的日期格式化样式(style);另外一种是通过某些说明符来手动设置日期格式。
我们先开始使用第一种方式,这里你会用到 NSDateFormatterStyle 的枚举类型,它有若干个枚举值,每个值都代表不同的样式。我们来逐个查看。第一个样式叫完整样式(FullStyle),它的结果显示如下:
t44_2_convert_fullstyle.png
下面是代码,可以自己拷贝粘贴试试效果:

dateFormatter.dateStyle = NSDateFormatterStyle.FullStyle
var convertedDate = dateFormatter.stringFromDate(currentDate)
除了日期样式的代码外,stringFromDate 方法的使用也很重要,它是真正执行转换的代码。当谈到日期、字符串转换时,就指的是这个方法,而其他步骤只是起到定制结果的辅助作用。如果你在项目里要用到日期转换,这个方法会非常方便。
接下来,我们来看一下长样式(Long Style):

dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
和完整样式比,长样式少了“天”的信息。
下来是 中等样式(Medium Style):
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
convertedDate = dateFormatter.stringFromDate(currentDate)
最后是 短样式(Short Style):
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
convertedDate = dateFormatter.stringFromDate(currentDate)
现在你就知道了有哪些可用的日期样式,在项目中可以根据需要在日期中使用。每个样式都会产生不同的结果,说不定哪个会适合你。
之前我提到过如何改变默认的区域设置,既然我们已经学习了改变formatter,影响日期转换结果的方式,接下来我们试着改变一下区域设置,看看会产生什么样的效果。在这个例子中,我会用完整样式来转换日期字符串,设置区域为希腊和法国。
我想这个截图很好的说明了区域的作用,你可以按照自己的需要设置。

使用日期格式说明符

预定义的日期样式在大多数情况下都可以适用,然而我们不能改变这些样式。若我们需要使用不同的格式,有一个方法:设置 自定义的日期格式 。设置自定义日期格式在两种场景中很有用:
1.当预定义的日期样式不能满足我们的需求;
2.当我们需要把一个复杂的日期字符串(比如Thu,08 Oct 2015 09:22:33 GMT)转换成日期对象。
要想设置合适的日期格式(对象),必须搭配使用一系列说明符。说明符也是简单的字符,但是对于date formatter来说有特定的含义。在查看具体的例子前,我们先列出一些在例子中出现的说明符:

EEEE:“星期”的全名(比如Monday)。如需缩写,指定1-3个字符(如E,EE,EEE代表Mon)。
MMMM:“月份”的全名(比如October)。如需缩写,指定1-3个字符(如M,MM,MMM代表Oct)。
dd:某月的第几天(例如,09或15)
yyyy:四位字符串表示“年”(例如2015)
HH:两位字符串表示“小时”(例如08或19)
mm:两位字符串表示“分钟”(例如05或54)
ss:两位字符串表示“秒”
zzz:三位字符串表示“时区”(例如GMT)
GGG:公元前BC或公元后AD
要查看完整的说明符文档,推荐访问http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns这个链接。
我们继续来看看这些说明符是如何发挥作用的。这次,让我们把当前时间转换成包含完整的星期、月份名称、日期和年份信息。

dateFormatter.dateFormat = “EEEE,MMMM dd,yyyy”
convertedDate = dateFormatter.stringFromDate(currentDate)
没有必要解释代码了,这个用法很直截了当。让我们再转换一个时间字符串:

dateFormatter.dateFormat = “HH:mm:ss”
convertedDate = dateFormatter.stringFromDate(currentDate)
到此,我们学到的转换都是把NSDate对象转成格式化的字符串对象。这个的逆过程也挺有意思,就是将格式化的字符串通过date formatter转换成 NSDate 对象,这里同样也会用到之前的日期样式和格式说明符。关键是要通过设置好的date formatter 对象调用 dateFromString ,让我们来看个例子:

var dateAsstring = “24-12-2015 23:59”
dateFormatter.dateFormat = “dd-MM-yyyy HH:mm”
var newDate = dateFormatter.dateFromString(dateAsstring)
让我们看个包含时区信息的复杂字符串:
dateAsstring = “Thu,08 Oct 2015 09:22:33 GMT”
dateFormatter.dateFormat = “EEE,dd MMM yyyy HH:mm:ss zzz”
newDate = dateFormatter.dateFromString(dateAsstring)
现在可以看到时间值(09:22)变成了12:22,这时因为时区生效了,实际上,时间并没有发生变换,这个时间(12:22)是GMT时间(09:22)加上我当前时区(EET:GMT+3)的时差后的结果。稍后我们会再看几个时区的例子,不过现在你可以在自己的机器上试一下效果。

到此,你已经掌握了日期、字符串间相互转换的知识。你可以自己尝试写写代码,来理解日期编程的原理。

使用NSDateComponents

许多情况下你需要把日期拆成块,并且获取某一项的值。例如,你可能只需要获取星期、月份或时间、小时信息。这时就要用到 NSDateComponents 类。
NSDateComponents 类经常和 NSCalendar 类搭配使用,NSCalendar 真正执行 NSDate 和 NSDateComponents 间的转换。这样,我们先要获取当前的calendar。

let calendar = NSCalendar.currentCalendar()
现在,我们来看一个NSDateNSDateComponents转换的具体例子:
let dateComponents = calendar.components([NSCalendarUnit.Day,NSCalendarUnit.Month,NSCalendarUnit.Year,NSCalendarUnit.WeekOfYear,NSCalendarUnit.Hour,NSCalendarUnit.Minute,NSCalendarUnit.Second,NSCalendarUnit.Nanosecond],fromDate: currentDate)

print(“day = (dateComponents.day)”,“month = (dateComponents.month)”,“year = (dateComponents.year)”,“week of year = (dateComponents.weekOfYear)”,“hour = (dateComponents.hour)”,“minute = (dateComponents.minute)”,“second = (dateComponents.second)”,“nanosecond = (dateComponents.nanosecond)”,separator: “,“,terminator: “”)
第一行用的方法是 NSCalendar 的 components(_:fromDate:),这个方法接受两个参数:第二个是日期对象;第一个参数比较有意思,它接收若干个 NSCalendarUnit 类型值,NSCAlendarUnit 用来说明需要的日期部分。
NSCalendarUnit 是一个结构体,你可以在 这个文档 中看到所有属性。在上面的例子中你可以看出,NSCalendarUnit 指定了以下日期组件:




一年中的第几个星期
小时
分钟

毫微秒
这里需要注意:若某个组件没有在第一个参数中指定,就无法访问它。如:在这个例子中,我们没有指定 NSCalendarUnit.TimeZone,这样就无法访问时区的组件,比如print(dateComponents.timezone)调用会造成一个运行时错误。如果你需要额外的日期组件,只能重新调用一次calendar.Components方法,把你需要的Calendar Unit添加进去。
date components到date对象的转换也很简单。这个过程中不需要使用calendar unit。只用初始换一个新的 NSDateComponents 对象,然后显式的设置你需要的组件的值,然后调用 NSCalendar 的 dateFromComponents 方法即可。
let components = NSDateComponents()
components.day = 5
components.month = 01
components.year = 2016
components.hour = 19
components.minute = 30
newDate = calendar.dateFromComponents(components)
在文章的前面我们看到了如何通过设置时区来影响转换的字符串,如果你想知道改动时区会对转换日期对象有怎样的影响,可以参考下面的例子:
components.timeZone = NSTimeZone(abbreviation: “GMT”)
newDate = calendar.dateFromComponents(components)
components.timeZone = NSTimeZone(abbreviation: “CST”)
newDate = calendar.dateFromComponents(components)
components.timeZone = NSTimeZone(abbreviation: “CET”)
newDate = calendar.dateFromComponents(components)
GMT = Greenwich Mean Time(格林尼治标准时间)
CST = China Standard Time(中国标准时间)
CET = Central European Time(欧洲中部时间)
你可以在 这个链接 中查找时区缩写的列表。
现在你已经知道了怎么使用 NSDateComponents ,让我们再来学习其他有趣的东西。

比较日期和时间

另外一个使用场景是比对日期对象,查看一个日期是否早于、晚于或等于另外一个日期。简单说来,我会提供三种方法来比对日期对象,但不会说明哪种方法比较好一些,这些方法的差别不大,到底用哪个取决于你的需求。

开始接触比较方法之前,我们先创建两个自定义的日期对象作为示例。初始化两个date formatter对象,通过它们将格式化字符串转换成日期对象。
teFormatter.dateFormat = “MMM dd,yyyy zzz”
dateAsstring = “Oct 08,2015 GMT”
var date1 = dateFormatter.dateFromString(dateAsstring)!

dateAsstring = “Oct 10,2015 GMT”
var date2 = dateFormatter.dateFromString(dateAsstring)!
先来看看第一个日期比对方法,它用于判断一个日期是否早于另外一个日期。方法名为 earlierDate:,还有一个是 laterDate:,例如:
date1.earlierDate(date2)
这个方法效果如下:

如果 date1 早于 date2,该方法返回date1
如过 date2 早于 date1,该方法返回date2
如果 date1 和 date2 相同,返回date1
laterDate 方法也可以用于这样的判断。
让我们来看一个用到这两个方法的例子:

// Comparing dates - Method #1
print(“Earlier date is: (date1.earlierDate(date2))”)
print(“Later date is: (date1.laterDate(date2))”)
另外一个日期比较方法是 NSDate 的 compare: 方法,它需要搭配使用 NSComparisonResult 枚举体。通过下面的例子你就能明白我说的意思。先让我们来看一下它的使用场景:同样,我们有两个日期对象需要比对,然后判断两个日期是否相同,如果不同,哪个更早一些。代码如下:
// Comparing dates - Method #2
if date1.compare(date2) == NSComparisonResult.OrderedDescending {
print(“Date1 is Later than Date2”)
}
else if date1.compare(date2) == NSComparisonResult.OrderedAscending {
print(“Date1 is Earlier than Date2”)
}
else if date1.compare(date2) == NSComparisonResult.OrderedSame {
print(“Same dates”)
}
第三个比对方法有点不同,因为它用到了时间间隔(time interval)的概念。这个方法也很简单,它可以查找到每个日期(到现在)的时间间隔,接下来就可以进行比对。

// Comparing dates - Method #3
if date1.timeIntervalSinceReferenceDate > date2.timeIntervalSinceReferenceDate {
print(“Date1 is Later than Date2”)
}
else if date1.timeIntervalSinceReferenceDate < date2.timeIntervalSinceReferenceDate {
print(“Date1 is Earlier than Date2”)
}
else {
print(“Same dates”)
}
上面的这些方法也可以用到时间的比对上。现在我给大家最后一个例子,这个例子和前面的不同之处在于 date1 和 date2 对象包含了时间的表示。例子中又用到了earlierDate 方法,另外,还用到了isEqualToDate:的方法,它的用法也很明显:

// Comparing time.
dateFormatter.dateFormat = “HH:mm:ss zzz”
dateAsstring = “14:28:16 GMT”
date1 = dateFormatter.dateFromString(dateAsstring)!
dateAsstring = “19:53:12 GMT”
date2 = dateFormatter.dateFromString(dateAsstring)!
if date1.earlierDate(date2) == date1 {
if date1.isEqualToDate(date2) {
print(“Same time”)
}
else {
print(“(date1) is earlier than (date2)”)
}
}
else {
print(“(date2) is earlier than (date1)”)
}
在其中你会看到“2000-01-01”的日期,你一定很好奇,因为我们从来没设置过这样的日期。这是因为若 NSDate 对象没有指定日期,只指定时间的话,会自动添加默认的日期属性。这不会影响到我们需要的时间值。

好了,现在你应该知道了如何比较日期对象了。

计算未来和过去的日期

计算过去和未来的日期比较有意思。这里你会用到 NSCalendarUnit,NSDateComponents 等之前了解过的工具。在下面的例子中,我会展示两种不同的方法:第一种使用 NSCalendar 类和 NSCalendarUnit 结构体;第二种使用 NSDateComponents 类。最后,我们会用到第三种替代方案,但是通常情况下,不推荐使用。
首先,记住我们的当前日期(当然了,是在写这个教程是的日期、时间)。这个日期会作为我们的参照值。

现在,假定我们需要为这个日期往后推两个月又5天。最好用代码来描述:

let monthsToAdd = 2
let daysToAdd = 5
我们先用第一种方法来获取期望的日期,先看看代码,稍后我会解释:
var calculatedDate = NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.Month,value: monthsToAdd,toDate: currentDate,options: NSCalendarOptions.init(rawValue: 0))
calculatedDate = NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.Day,value: daysToAdd,toDate: calculatedDate!,options: NSCalendarOptions.init(rawValue: 0))
如你所见,这里用到的方法是 NSCAlendar 类的 dateByAddingUnit:value:toDate:options: 方法。它的作用是添加某个日历单元值(如年月日时分秒等)到现有的日期对象上,然后返回新的日期对象。我们需要添加两个日历单元到当前日期,直接用这个方法是不可能的(它每次只能设置一个calendar unit)。关键是调用两次这个方法,设置不同的日历单元,就能得到最终结果。
以下是在playground中调用效果,你可以看到两次添加的结果:
这个方法在你需要设置1~2个日历单元时,还是不错的。当日历单元多的时候,你就需要多次调用这个方法。
在日历单元比较多的时候,更好的方法是使用 NSDateComponents 类。方便起见,这个例子中我们还是设置月份和天。具体做法是:初始化一个 NSDateComponents 对象,并设置月份和天的信息。然后我们调用 NSCalendar 的另一个方法 dateByAddingComponents:toDate:options:,并最终获得我们需要的日期对象。

let newDateComponents = NSDateComponents()
newDateComponents.month = monthsToAdd
newDateComponents.day = daysToAdd

calculatedDate = NSCalendar.currentCalendar().dateByAddingComponents(newDateComponents,options: NSCalendarOptions.init(rawValue: 0))
注意:在以上调用 NSCalendar 方法的地方,最后一个参数options都没有被设置。如果你需要具体设置options的值,请参考完整的 官方文档。
第三种方法实际上并不推荐使用,因为闰秒、闰年或日光节约时间的缘故,它经常会得到错误的结果。这个方法的思路是为当前的日期添加一个时间段。我们会用到 NSDate 的 dateByAddingTimeInterval: 方法。在下面的例子中,我们要获得计算1.5小时后的时间。

let hoursToAddInSeconds: NSTimeInterval = 90 * 60
calculatedDate = currentDate.dateByAddingTimeInterval(hoursToAddInSeconds)
再次说明一下,上述的前两种方法更安全和通用。你可以按照需求选择使用。
上面的三个例子都是为当前日期对象添加某些日历单元的值。那么如何通过减去一些天数来获取之前的日期?
接下来的例子可以完成这个任务。首先,我们可以为当前日期添加一个负值,这样就可以得到之前的日期。然后通过格式化的方式获取字符串结果。这个结果比较有意思。

let numberOfDays = -5684718
calculatedDate = NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.Day,value: numberOfDays,options: NSCalendarOptions.init(rawValue: 0))

dateFormatter.dateFormat = “EEEE,MMM dd,yyyy GGG”
dateAsstring = dateFormatter.stringFromDate(calculatedDate!)
上面的这些代码片段可以帮助你理解计算过去和之前日期的方法。你可以自己试试改变这些代码,看看有什么不一样的结果。这样就可以更深入的理解这些功能。

计算日期间隔

正如开头说的那样,计算日期间隔也是你在工作过程中可能遇到的任务。在教程的最后部分,我将通过三种方式展示如何计算 NSDate 对象的间隔。你可以按照需要选择适用的方法。
首先,我们还是需要创建两个自定义的 NSDate 对象:

dateFormatter.dateFormat = “yyyy-MM-dd HH:mm:ss”
dateAsstring = “2015-10-08 14:25:37”
date1 = dateFormatter.dateFromString(dateAsstring)!

dateAsstring = “2018-03-05 08:14:19”
date2 = dateFormatter.dateFromString(dateAsstring)!
我们先来看看如何通过date components来计算日期对象间隔。我们又会用到 NSCalendar 类的一个方法。然后打印出各个日期部分的结果。显然,只要有可用的date components,通过这种方法获取需要的结果是很简单的:

var diffDateComponents = NSCalendar.currentCalendar().components([NSCalendarUnit.Year,NSCalendarUnit.Day,NSCalendarUnit.Second],fromDate: date1,toDate: date2,options: NSCalendarOptions.init(rawValue: 0))

print(“The difference between dates is: (diffDateComponents.year) years,(diffDateComponents.month) months,(diffDateComponents.day) days,(diffDateComponents.hour) hours,(diffDateComponents.minute) minutes,(diffDateComponents.second) seconds”)
这个新方法叫 components:fromDate:toDate:options:,第一个参数是 NSCalendarUnit 值的数组。这里要注意,如果第一个日期如果晚于第二个日期,则结果会返回负值。
另外两种方法中,我们将第一次用到 NSDateComponentsFormatter 类,它提供了多种用于自动计算日期间隔的方法,并可以返回格式化字符串结果。首先,我们创建一个date components formatter对象,这里只指定一个属性:

let dateComponentsFormatter = NSDateComponentsFormatter()
dateComponentsFormatter.unitsstyle = NSDateComponentsFormatterUnitsstyle.Full
unitsstyle 属性指定我们使用的 dateComponentsFormatter 以何种格式打印日期的间隔。例如,这里我们使用 完整 样式,这样天数、月数等名字(如days,months)都会被显示出来。如果我们设置 缩写 样式,就会显示缩写名字(天数显示为d等)。你可以在 这个链接 中查找到所有的样式:
让我们继续会到日期间隔计算的话题上。我们先计算日期的间隔,再把该值传递给stringFromTimeInterval:方法,这样,就能获得日期间隔的字符串表示:
let interval = date2.timeIntervalSinceDate(date1)
dateComponentsFormatter.stringFromTimeInterval(interval)
最后,第三种计算的方法中,我们将两个日期传递给 NSDateComponentsFormatter 对象的一个叫 stringFromDate:toDate: 的方法。但是这个方法需要有个前置的条件:NSDateComponentsFormatter 的 allowedUnits 属性必须被提前设置,这个属性接受数组类型的值,这里至少要设置一个日历单元的值。否则这个方法会返回nil值。所以,在这个方法的使用中,我们“告诉”它需要获取哪些日历单元,它会按照对应的日历单元返回结果:

dateComponentsFormatter.allowedUnits = [NSCalendarUnit.Year,NSCalendarUnit.Second]
let autoFormattedDifference = dateComponentsFormatter.stringFromDate(date1,toDate: date2)
总结

正如我之前提到的,NSDate对象在工程中很常用,无可避免。不可否认,它在程序员的讨论话题中并不怎么出名,因此,我尝试通过一些小的例子来说明日期编程并没有什么复杂之处。教程中提到的NSDate和其他相关类都说明了,通过两三行代码就可以完成你的工作。希望这个教程可以帮助到你,尤其是当你刚接触到这方面的编程。

NSDate教程Swift版的更多相关文章

  1. ios – 无法识别的选择器发送到实例NSTimer Swift

    解决方法让updateTime成为一个类方法.如果它是在一个纯粹的Swift类中,你需要在@objc前面说明该方法的声明,如:

  2. ios – 类型推断(自动类型检测)如何在swift中工作?

    LLVM如何检测变量是一个字符串?

  3. ios – Swift可选项:语言问题,还是做错了什么?

    应该有可选的类型;type是但是,如果我这样做,它的工作原理:它似乎是基本的替代,但我可能会遗漏一些语言的细微差别.谁能对此有所了解?之后就像暧昧一样,更多,这是我的解决方案:这适用于所有非对象Swift对象,包括Swift字符串,数字等.感谢Viktor提醒我String不是Swift中的对象.如果您知道值的类型,您可以替换任何?使用适当的可选类型,如String?

  4. ios – 覆盖Swift中的超类委托

    我正在开发一个包含两个UIViews的Swift(v1.2)项目.MyView和MyViewSubclass.MyView有一个委托,我想在MyViewSubclass中覆盖它作为一个子协议,类似于UITableViews有一个UITableViewDelegate,它也符合超级uiscrollviewdelegate.我的第一个想法是覆盖超类属性,但这会导致编译器错误,因为子类不能覆盖具有不同类

  5. ios – 我可以在swift中将字符串转换为代码块吗?

    有没有办法将字符串转换为代码块?

  6. ios – Swift:方法重载只在返回类型上有所不同

    我一直在看Swift类,其中定义了两种方法,它们的返回类型不同.我不习惯使用允许这种语言的语言,所以我去寻找描述它如何在Swift中工作的文档.我在任何地方都找不到任何东西.我本来期望在Swift书中有关于它的整个部分.这记录在哪里?

  7. ios – 字符串资源Xcode swift

    我是iOS开发和Swift语言的新功能.而且我尝试制作简单的iOS应用程序,我需要在应用程序中使用一些字符串资源.当然,我可以将这个字符串放在我的*.swift文件中作为常量,但我认为这是一个坏的方法.我该怎么做?

  8. ios – 如何使用新的Apple Swift语言发布JSON

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  9. ios – Swift元组到可选分配

    我在Swift编写一些代码来学习语言.这是我的基础课:问题在最后一行:编译器说“不能表达元组转换to”我明白问题是self.status和self.message是可选的,parseResponse不返回可选.我如何告诉它做必要的分配和转换,以获取数据到实例变量?

  10. ios – 使用未申报的“AppDelegate”Swift

    您可能会看到AppDelegate代码here,但是我没有修改任何由xCode自动生成的内容.我创建了一个具有this设置的单一视图应用程序.解决方法很有可能当您创建项目时,您还创建了一个“{ProjectName}Tests”目标.问题是AppDelegate没有在“{ProjectName}Tests”目标中分配成员资格.选择AppDelegate.swift,然后在右侧检查器中单击文件检查器,然后确保在“目标成员资格”中,您的项目和测试目标复选标记都设置为ON.清洁,重建.

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部