使用DateFormatter从API格式化日期和时间

我最近学习了如何访问API和解析JSON,从而在Swift编程中解锁了一套全新的技能,尽管它非常酷,但也可能非常令人沮丧。 除了弄清楚如何布置返回的数据外,我遇到的第一个主要问题是尝试从某个API获取日期和时间。

有关更多信息,我使用了SeatGeek API,以构建一个显示2017年纽约洋​​基日程的应用程序。 SeatGeek API有大量信息可以解析,但我主要专注于抓住对手,游戏的位置,日期和时间。 一旦找到数据所在的位置,通过它们进行解析就不会太糟糕。

但是,我遇到的最大麻烦是将日期和时间捆绑在一起,称为“ datetime_local”。我想分别设置日期和时间,以便最终将它们显示在应用程序的两个标签上。 格式如下所示:

“ 2017–04–02T13:10:00”

看来,第一部分是日期(2017年4月2日),第二部分是时间(标准时间13:00:00或1:10 pm)。 好的,没问题,我将仅使用字符串实例上可用的“ components”方法。 看起来好像用“ T”分隔了它们,所以我们用它来分隔:

如果您不熟悉,则“ components”函数将采用分隔的字符串并将它们放入数组中。 因此,日期是数组中的第一项(索引0),时间是第二项(索引1),因此我们可以按以下方式访问它们:

因此,现在我有了单独的日期和时间值,但我希望最终将这些值显示给用户,但我不了解您,但是如果我在应用程序中看到这些值,则将其关闭并立即将其删除。 相反,我想将这些日期和时间转换为更易读,用户友好的格式。 而这就是混乱的源头。

让我们回顾一下上面那种奇怪的“ datetime_local”格式。 我不知道的是,这种格式实际上非常普遍,被称为ISO8601。它本质上是一种约定的日期和时间格式,因此信息可以在国际范围内发送而不会造成混乱(讽刺的是,这是造成我的原因)最混乱)。 它的格式设置是从最大的时间开始,直到下一年(月-日-日)都用连字符隔开。 之后,“ T”基本上用作分隔符,表示“好,我们正在过渡到现在的时间”,并且以与日期类似的方式列出时间,从大到小(小时:分钟:秒),并带有一个冒号分隔每个。 同样重要的是要注意,ISO 8601默认为军事时间(24小时制),这可能有点令人沮丧。 这些都是ISO 8601的基础,但是,如果您有兴趣阅读有关坚韧不拔的文章,可以在https://en.wikipedia.org/wiki/ISO_8601上找到更多信息。

好吧,回到当前的问题-尝试将日期和时间转换为可读的,用户友好的值。 实际上,有两种方法可以执行此操作,具体取决于您要执行的操作,但是无论如何,您都必须在Swift中使用DateFormatter。 那么什么是DateFormatter?

DateFormatter实际上是Apple定义的类,可帮助转换日期和实际时间。 DateFormatters上具有多种方法,您可以调用这些方法来获取/设置值,这是它们变得最有用的地方。

解决该问题的第一种方法是创建一个函数以从ISO 8601格式提取日期。 在我们的例子中,让我们想像一下,我们还没有分开日期和时间,它仍然以ISO 8601中格式化的奇怪的“ datetime_local”键下降。如果需要,我们实际上可以从日期中删除日期:

好吧,这是怎么回事? 首先,我们设置自己的dateFormatter常量,它是DateFormatter的一个实例。 DateFormatter的所有实例上都有一个名为Calendar的属性,我们可以使用该属性来设置数据输入的日历类型。 看看那个! 苹果实际上是.iso8601的选项之一! 然后,我们为该初始dateFormatter设置日期格式,在我们的情况下就是ISO 8601的样子-“ yyyy-MM-dd’T’hh:mm:ss”。

设置完初始dateFormatter之后,实际上我们需要创建一个新的dateFormatter。 可以这样想:“这是我要传递的字符串的格式为(我们的初始dateFormatter),这是我希望将其转换为(我们的newFormat)的内容。”因此,我们声明了另一个常量,称为newFormat,这是另一个常量DateFormatter的实例,并将其dateFormat属性设置为我们希望我们的原始字符串变为“ MMM dd”。此格式将输出该月的前三个字母,然后是日期(因此2017–04–02变为4月2日)。 有关日期和时间格式的更多信息,请参见此博客文章的结尾。

现在是棘手的部分。 我们需要发送要转换的字符串,它实际上完成了两次(每个格式化程序一个)。 因此,我们首先解包并发送字符串以将其转换为Date,这实际上是Swift中的另一种类型。 现在我们有一个日期仍然是我们的原始格式(yyyy-MM-dd’T’hh:mm:ss),但我们不仅希望以其他格式返回它,而且还希望它是一个String而不是一个约会。 因此,我们通过第二个格式化程序将其发送,执行相反的操作:将Date转换为String并将其格式化为所需格式(在本例中为MMM dd)。 如果运行该代码,您将看到我们新的String现在已经按照我们想要的方式格式化了!

那是解决问题的一种方式,但是我觉得那有点太多,因为我不得不暂时创建另一个函数来完成它,而且我已经将“ datetime_local”数据分成了两个不同的字符串。 因此,我将上面的函数一点一点地改了一下,重新编写了其中的一些内容,以便确切地得到我想要的东西:

哇 我知道那看起来很多。 但是对我的大脑来说,这实际上更有意义,因为我明确地告诉了日期和时间该怎么做。 让我们细分一下:

我首先声明了两个空字符串,称为convertedDate和convertedTime。 稍后,这些将成为我要使用的实际日期和时间。 然后,我设置了四个DateFormatter,两个用于日期,两个用于时间。 如您所见,日期和时间的第一个格式化程序是我的字符串将以的格式输入,并且由于我稍后将对其进行分隔,因此我知道日期的格式将为“ yyyy- MM-dd”和时间格式将为“ HH:mm:ss”。日期和时间的第二个格式化程序设置了我希望将转换后的值格式化为的格式。 对于日期,我希望它是“ MMM d”(给我该月和该日的前三个字母-再次,请参见下面的有关d vs dd格式的更多信息)和时间我希望它是“ h:mm a”(因为我不关心秒数就是小时和分钟,请参阅下面的“ a”的含义,但本质上将其放在AM或PM中)。

设置好所有转换器之后,我现在可以从API提取数据,进行分离和转换:

Guard let语句为我打开了“ datetime_local”值,然后运行.components方法以ISO 8601格式用“ T”分隔字符串。 请记住,这会将每个String放入数组,因此我将两个常量(splitDate和splitTime)设置为等于我的每个分割值。 然后,我通过转换器运行这些拆分字符串中的每一个,完全按照我们在上面的函数中所做的操作-将String转换为初始格式的Date,然后将该Date转换为新格式的String,设置新值等于我们在上面创建的空字符串(convertedDate和convertedTime)

现在,如果我要运行代码并打印出这些值,我会看到,对于原始的datetime_local字符串“ 2017–04–02T13:10:00”,我将获得“ Apr 2”作为日期,并返回“ 1:10 PM” ”。 对于用户而言,这更容易阅读:

可能要进行大量排序,但是一旦您了解了使用DateFormatters的概念,并且本质上不得不两次发送内容,转换日期就变得容易得多!

最后,按照承诺,我将简要介绍不同的日期和时间格式。

关于日期和时间格式,有很多细微差别,其中大部分集中在您是否想要/有多少个零。 例如,只有一个“ M”的日期格式将为您提供至少一个数字的月份,因此“五月”将转换为“ 5”,十月将转换为“ 10”。 “ MM”会将“ May”转换为“ 05”,将October转换为“ 10”。看到区别了吗? 基本上,每当您不希望任何输出都用零填充时,请使用单个字母。

日期格式的另一个有趣的细微差别是能够获取一个月或一周中某天的实际单词。 实际上,根据使用的格式,您可以获得一个单词的许多变体。 例如,如果您尝试获取星期几,则“ EEE”将为您提供三个字母的缩写(因此“ Monday”变为“ Mon”),“ EEEE”将为您提供全名,而“ EEEEE”将为您给您当天的第一封信。

最后,时间格式可以为您带来不同的结果。 如果您还记得上面的示例,则使用“ h:mm”格式来获取标准的12小时制。 这是因为小写的“ h”以标准的12小时制表示时间,而大写的“ H”以24小时制表示格式。 与日期类似,您使用的字母数决定是否用零填充数字。 有关日期和时间格式的更多信息,建议您访问http://www.codingexplorer.com/swiftly-getting-human-可读-date-nsdateformatter /。

日期和时间格式肯定需要练习,但是如果要解析JSON以查找日期和时间,则这绝对是一项必不可少的技能。 我建议您使用不同的时间格式,并从不同的API中提取数据以进行练习!