Let’s create a new playground, and import Foundation at the top.

  import Foundation

As we've hinted at previously, importing a module makes its type available in the current file. Unlike a C #include compiler directive, there are no header sources copied into the current file. Instead, each module defines what is exports, which we'll cover another week.

URL’s

First, we'll cover URL's.

  var url:URL? = URL(string:"https://www.apple.com")
  //https://www.apple.com

The first thing to notice is that the URL init(string: method does not guarantee it will create a URL from the String. The String must be correctly-formatted in order for this to work. Let’s see it fail, by making the url invalid, by using a space character:

  var url:URL? = URL(string:" ")      //nil

This means in code, you cannot assume that creating a URL will succeed, so please don’t force-unwrap the optional. However, it does mean that if you require a URL in your API, it means validation will have already taken place.

That works for creating a URL to the internet.

  var url:URL = URL(fileURLWithPath:"/users/ben/Documents/Swift 14 Foundation.md")

For URL’s to files need to be constructed specially if you already have a path String:

Notice that we’re making a pretty big deal out of the fact that one is a file and the other is not.

  var url:URL? = URL(string:"file:///users/ben/Documents/Swift%2014%20Foundation.md")

You can create a file URL with the string: init function, but you’ll need to make sure you include the correct scheme, leave out the domain, and convert the spaces to precent escape encoding, so in other words, if you need to take a string path from another API, use the URL(fileURLWithPath: init function to convert.

There is a property on the URL, .isFileURL, which will directly let you know if a URL is actually a file. This is preferred over, for instance, using .hasPrefix("file:///") on a String.

  var isAFile:Bool = stringURL.hasPrefix("file:///")  //anti-pattern
  var isAFile:Bool = url.isFileURL    // thumbsup

For working with paths, URL knows how to pull out path components into an array:

  var pathComponents:[String]? = URL(string:"https://developer.apple.com/wwdc/live")?.pathComponents
  // ["/", "wwdc", "live"]

Or read the extension:

  var fileExtension:String? = URL(fileURLWithPath:"/video.mp4").pathExtension

It also knows how to modify a url to add more path components:

  var urlWithPath:URL? = URL(string:"https://developer.apple.com/wwdc/live")
  try! urlWithPath?.appendPathComponent("slides")
  urlWithPath      //https://developer.apple.com/wwdc/live/slides

Many platforms rely on the use of strings to refer to files or internet resources, but Foundation provides a custom value type, URL. When importing a String from another source that should be represented with a URL, convert them immediately, leaving the interior of your code to work with this canonical type.

URLComponents - a Builder pattern

  var scheme:String? = url.scheme
  var host:String? = url.host
  var query:String? = url.query

The URL struct does provide read-only properties for extracting the pieces of a URL, like scheme, host, and query in this example. But they don’t allow direct setting, so let’s take a look at a companion struct, URLComponents.

  var components = URLComponents()
  components.scheme = "https"
  components.host = "developer.apple.com"
  components.path = "/wwdc/live"
  components.user = "jonny"
  components.password = "1P40n3"
  components.queryItems = [URLQueryItem(name: "skip", value: "20"),
  URLQueryItem(name: "search", value: "Best Practices")]

URLComponents is what’s known as a "Builder" pattern. It’s an object whose properties are configured one at a time, and then it produces a manufactured object, a URL. This lets us forget about formatting, and set each field directly.

  let url:URL = components.url
  //https://jonny:1P40n3@developer.apple.com/wwdc/live?skip=20&search=Best%20Practices

Then let the components type take care of creating a correctly-formatted URL for me:

Notice that the query parameters automatically got percent escaping for the right characters. Also notice that the query items are an Array, not a Dictionary, since the URL spec does not prevent a query key from appearing more than once.

One might even imagine that instead of passing URL’s through various layers of an app, each one tacking on different fields with very carefully calculated string offsets, only the URLComponents would be passed around, with each layer of the app modifying it to its heart’s content, only to be turned into a perfectly formatted URL at the very end. In short, this is a grand slam for value types in Swift over the Class / Mutable Class Obj-C architecture.

Dates

Foundation provides basic date/time-types. There is a Date, which represents an absolute position in time:

  let now:Date = Date()

The empty initializer gives us "now".

We can also construct a Date with a Unix system time:

  let someSpecificTime = Date(timeIntervalSince1970:4567.0)

By using the word since, the init method’s intention is to make Dates after 1970 have a positive value, and Dates before negative.

Similarly, we construct a date moments into the future using:

  let nearFuture = Date(timeIntervalSinceNow:0.4)

We can compute the TimeInterval between two Dates, which is simply a typealias of a Float64, using

  now.timeIntervalSince(Date(timeIntervalSinceNow: 10.0))
  //-10.004

You’ll notice you don’t quite get a perfect "10.0" because it takes milliseconds for the playground to move between these computations.

And again, the values are positive if the receiver is after the argument date, negative if it is before the argument date.

Alternatively, if we need to add small time intervals to a given date, Date provides simple math operations:

Date can also add small time intervals:

  var nearFuture = now.addingTimeInterval(0.4)
  nearFuture.addTimeInterval(0.2)

I recommend you pretty much never do this, however, because a Date is just a time interval since 1970. Since clocks are constantly changing to try to adjust for various political time changes and minute variations in the inaccuracy of our conventions, like 365-day years, or 24-hour days, merely adding time intervals to dates will not always get you what you want.

Just as we had a URL to represent a single fully-composed URL, and used URLComponents to create them, we’ll use DateComponents to build Dates.

  var components = DateComponents()
  components.year = 2016
  components.month = 3
  components.day = 1
  components.hour = 17
  components.minute = 32
  components.second = 12
  components.calendar = Calendar.init(identifier: .gregorian)
  components.timeZone = TimeZone.current

  let date = components.date  //"Mar 1, 2016, 5:32 PM"

This constructed a Date for us, without our having to do any math, or know anything about leap years. Notice that we needed to get a Calendar to make the components work. This is necessary, because although a single point in time represented by a Date is the same in each Calendar system, the way to break down the years, months, days, etc… are not the same.

Unlike arrays which use 0-based indexes, DateComponents is 1-based. In other words, Jan 1, has

  .month = 1
  .day = 1

This means that we won’t need to alter any numeric values from when converting from the user’s writing or to display.

`DateComponents` are also useful in performing math operations on `Date`s.

  var difference = DateComponents()
  difference.day = -1
  let future = gregorianCalender.date(byAdding: difference, to: date)
  //"Feb 29, 2016, 5:32 PM"

Here, we create a blank set of DateComponents, then set a -1 for the .day. Then we ask the calendar to perform the math, giving us a new Date. Without needing to know anything about leap years, Foundation has provided us with the correct date before. In general, using components and Calendar-based math in this way helps us entirely avoid Date math problems, like leap years, and daylight savings time.

Summary

Today we learned the Foundation module, which ships with Swift, has many standard types used for building representing real values. Among those are URLs, which represent both files and web resources, and Dates which represent moments in time. Both have a Components companion type which provide a "builder" pattern. The components provide direct meaningful access to the meaningful pieces of the larger types, and assemble one correctly on demand.

A standard library with value types for representing real-world values, now that's Swift!