title: How to extend Codable functionality of Date and other built in types?
body: <p>I am trying to extend the functionality of <code>Date.init(from:Decoder)</code> to handle different formats passed from my server. Sometimes a date will be encoded as a string, sometimes that string nested in a dictionary. According to the Swift source, <code>Date</code> is decoded/encoded like: </p>
  
  <pre><code>extension Date : Codable {
      public init(from decoder: Decoder) throws {
          let container = try decoder.singleValueContainer()
          let timestamp = try container.decode(Double.self)
          self.init(timeIntervalSinceReferenceDate: timestamp)
      }
  
      public func encode(to encoder: Encoder) throws {
          var container = encoder.singleValueContainer()
          try container.encode(self.timeIntervalSinceReferenceDate)
      }
  }
  </code></pre>
  
  <p>So I tried to extend that function as follows:</p>
  
  <pre><code>public extension Date {
  
      private enum CodingKeys: String, CodingKey {
          case datetime
      }
  
      public init(from decoder: Decoder) throws {
          let dateString: String
          if let container = try? decoder.container(keyedBy: CodingKeys.self) {
              dateString = try container.decode(String.self, forKey: .datetime)
          } else if let string = try? decoder.singleValueContainer().decode(String.self) {
              dateString = string
          } else {
              let timestamp = try decoder.singleValueContainer().decode(Double.self)
              self.init(timeIntervalSinceReferenceDate: timestamp)
              return
          }
          if let date = Utils.date(from: dateString) {
              self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate)
          } else if let date = Utils.date(from: dateString, with: "yyyy-MM-dd") {
              self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate)
          } else {
              let context = DecodingError.Context(codingPath: [], debugDescription: "Date format was unparseable.")
              throw DecodingError.dataCorrupted(context)
          }
      }
  
  }
  </code></pre>
  
  <p>However this function is never called. Then I tried to extend <code>KeyedDecodingContainer</code> to change <code>Date</code> decoding in the <code>decode(_:forKey)</code> as follows: </p>
  
  <pre><code>extension KeyedDecodingContainer {
  
      private enum TimeCodingKeys: String, CodingKey {
          case datetime
      }
  
      func decode(_ type: Date.Type, forKey key: K) throws -&gt; Date {
          let dateString: String
          if let timeContainer = try? self.nestedContainer(keyedBy: TimeCodingKeys.self, forKey: key) {
              dateString = try timeContainer.decode(String.self, forKey: .datetime)
          } else if let string = try? self.decode(String.self, forKey: key) {
              dateString = string
          } else {
              let value = try self.decode(Double.self, forKey: key)
              return Date(timeIntervalSinceReferenceDate: value)
          }
          if let date = Utils.date(from: dateString) {
              return date
          } else if let date = Utils.date(from: dateString, with: Globals.standardDateFormat) {
              return date
          } else {
              let context = DecodingError.Context(codingPath: [], debugDescription: "Date format was not parseable.")
              throw DecodingError.dataCorrupted(context)
          }
      }
  
  }
  </code></pre>
  
  <p>However, when this is called to decode a <code>Date</code> that I encoded by calling <code>container.encode(date, forKey: .date)</code>, I get a <code>typeMismatch</code> error that the data is not a <code>Double</code>. I am completely baffled as to what's going on, because the <code>encode(to:)</code> function for <code>Date</code> explicitly encodes a Double. I tried tracing my way through the <code>decode</code> calls in the Swift source code and it doesn't seem to ever call <code>Date.init(from:Decoder)</code>. </p>
  
  <p>So I am wondering, is it possible to alter the way the <code>Date</code> type is decoded through this kind of extension? Is my only option to duplicate my custom <code>Date</code> decoding in every single model? What on earth calls <code>init(from:Decoder)</code>?</p>