【问题标题】:Swift ISO 8601 date formattingSwift ISO 8601 日期格式
【发布时间】:2019-11-22 04:10:33
【问题描述】:

我正在对 randomuser.me 进行 api 调用并取回一个包含(以及其他数据)的 json 文件:

"dob": { "日期": "1993-07-20T09:44:18.674Z", “年龄”:26 }

我想在文本标签中将日期字符串显示为“dd-MMM-yyyy”,但不知道如何格式化字符串来实现这一点。

我尝试使用 ISO8601DateFormatter 将其转换为日期,然后再转换回字符串,但到目前为止还没有成功。

谁能帮忙?

func getUserData() {

    let config = URLSessionConfiguration.default
    config.urlCache = URLCache.shared
    let session = URLSession(configuration: config)

    let url = URL(string: "https://randomuser.me/api/?page=\(page)&results=20&seed=abc")!
    let urlRequest = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 15.0)
    let task = session.dataTask(with: urlRequest) { data, response, error in

        // Check for errors
        guard error == nil else {
            print ("error: \(error!)")
            return
        }
        // Check that data has been returned
        guard let content = data else {
            print("No data")
            return
        }

        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            let fetchedData = try decoder.decode(User.self, from: content)

            for entry in fetchedData.results {
                self.usersData.append(entry)
            }

            DispatchQueue.main.async {
                self.tableView.reloadData()
            }

        } catch let err {
            print("Err", err)
        }
    }
    // Execute the HTTP request
    task.resume()
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "userInfoCell") as! UserInfoCell

    let user: Result

    if isFiltering {
        user = filteredData[indexPath.row]
    } else {
        user = usersData[indexPath.row]
    }

    cell.nameLabel.text = "\(user.name.first) \(user.name.last)"
    cell.dateOfBirthLabel.text = user.dob.date
    cell.genderLabel.text = user.gender.rawValue
    cell.thumbnailImage.loadImageFromURL(user.picture.thumbnail)

    return cell
}

【问题讨论】:

    标签: json swift xcode uikit


    【解决方案1】:
    import Foundation
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
    let theDate = dateFormatter.date(from: "1993-07-20T09:44:18.674Z")!
    let newDateFormater = DateFormatter()
    newDateFormater.dateFormat = "dd-MMM-yyyy"
    print(newDateFormater.string(from: theDate))
    

    首先使用正确的日期格式将字符串转换为日期。然后使用您想要的格式将其转换回字符串。

    【讨论】:

    • 不需要newDateFormater。您可以使用相同的dateFormatter
    【解决方案2】:

    将您的日期传递到此

        let dateFormatterPrint = DateFormatter()
        dateFormatterPrint.dateFormat = "dd-MM-yyyy"
    
        let val = dateFormatterPrint.string(from: "pass your date")
    

    【讨论】:

      【解决方案3】:

      您可以使用扩展来将日期转换为您想要的格式。

      var todayDate = "1993-07-20T09:44:18.674Z"

      extension String {
      
          func convertDate(currentFormat: String, toFormat : String) ->  String {
              let dateFormator = DateFormatter()
              dateFormator.dateFormat = currentFormat
              let resultDate = dateFormator.date(from: self)
              dateFormator.dateFormat = toFormat
              return dateFormator.string(from: resultDate!)
          }
      }
      

      然后你可以这样实现:

      cell.dateOfBirthLabel.text = self.todayDate.convertDate(currentFormat: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", toFormat: "dd-MMM-yyyy")

      【讨论】:

        【解决方案4】:

        通常,如果手动将1993-07-20T09:44:18.674Z 转换为Date,我们会使用ISO8601DateFormatter

        let formatter = ISO8601DateFormatter()
        formatter.formatOptions.insert(.withFractionalSeconds)
        

        在这种方法中,它会为我们处理时区和语言环境。


        话虽如此,如果您使用JSONDecoder(以及下面概述的dateDecodingStrategy),那么我们应该将模型对象定义为使用Date 类型,而不是String 用于所有日期。然后我们告诉JSONDecoder 使用特定的dateDecodingStrategy 为我们解码Date 类型。

        但这不能使用ISO8601DateFormatter。我们必须使用DateFormatter"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"dateFormatLocale(identifier: "en_US_POSIX")locale

        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)  // this line only needed if you ever use the same formatter to convert `Date` objects back to strings, e.g. in `dateEncodingStrategy` of `JSONEncoder`
        
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .formatted(formatter)
        

        请参阅DateFormatterdocumentation 的“使用固定格式的日期表示”部分。


        然后,对于您的 UI 格式化程序,如果您绝对想要 dd-MMM-yyyy 格式,您将有一个单独的格式化程序,例如:

        let formatter = DateFormatter()
        formatter.dateFormat = "dd-MMM-yyyy"
        

        注意,对于这个 UI 日期格式化程序,我们没有设置 localetimeZone,而是让它使用设备的当前默认值。

        话虽如此,我们通常希望避免将dateFormat 用于UI 中显示的日期字符串。我们通常更喜欢dateStyle,它以用户喜欢的格式显示日期:

        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        

        这样,美国用户将看到“2019 年 11 月 22 日”,英国用户将看到“2019 年 11 月 22 日”,法国用户将看到“22 nov. 2019”。用户会以他们最习惯的格式查看日期。

        请参阅上述DateFormatterdocumentation 中的“使用用户可见的日期和时间表示”。

        【讨论】:

          猜你喜欢
          • 2015-05-01
          • 2016-03-06
          • 2013-05-22
          • 2017-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-28
          相关资源
          最近更新 更多