代码之家  ›  专栏  ›  技术社区  ›  Jake2Finn

将Unix时间从JSON导入(swift结构)转换为日期作为字符串并填充表

  •  0
  • Jake2Finn  · 技术社区  · 8 年前

    我有一个JSON文件正在导入到我的项目中( https://api.myjson.com/bins/ywv0k )JSON属性被解码并存储在我的结构类“news”中,它具有与JSON文件相同的属性。

    在第二步中,我用结构类“news”中的字符串属性“timestamp”填充一个表,它实际上是一个unix时间。

    我现在的问题是,由于我在尝试放置函数时遇到错误,所以无法将这个Unix时间更改为“dd/mm/yy hh:mm:ss”格式的字符串。

    let date = NSDate(timeIntervalSince1970: timestamp) //error since timestamp is currently defined as string. If I make it a long variable, I cannot populate the table with it any more, since the label requires a text with string format.
    
    let dayTimePeriodFormatter = NSDateFormatter()
    dayTimePeriodFormatter.dateFormat = "dd/mm/yy HH:mm:ss"
    
     let dateString = dayTimePeriodFormatter.stringFromDate(date)
    

    进入do encoding循环,以及当我将其放入此表函数时:func tableview(uuTableView:uiTableView,cellForRowat indexPath:indexPath)->uiTableViewCell。

    斯威夫特4

    import UIKit
    
    // structure from json file
    struct News: Codable{
        let type: String
        let timestamp: String // UNIX format, eg. "1531294146340"
        let title: String
        let message: String
    }
    
    class HomeVC: BaseViewController, UITableViewDelegate, UITableViewDataSource {
        var myNewsItems: [News] = []
        @IBOutlet weak var myNewTableView: UITableView!   
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let nibName = UINib(nibName: "CustomTableViewCell", bundle: nil)
            myNewTableView.register(nibName, forCellReuseIdentifier: "tableViewCell")
    
    
    // JSON Decoding
    
            let url=URL(string:"https://api.myjson.com/bins/ywv0k")
            let session = URLSession.shared
            let task = session.dataTask(with: url!) { (data, response, error) in
    
                guard let data = data else { return }
    
                do {
                    let myNewsS = try
                        JSONDecoder().decode([News].self, from: data)
                    print(myNewsS)
    
                    self.myNewsItems = myNewsS
                    DispatchQueue.main.async {
                        self.myNewTableView.reloadData()
                    }
                } catch let jsonErr {
                }
    
            }
            task.resume()
        }
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return myNewsItems.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as!
    CustomTableViewCell
    
    // populate table with json content
            cell.commonInit(timestamp: myNewsItems[indexPath.row].timestamp, message: myNewsItems[indexPath.row].message)
    
            return cell
        }
    
        func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
                cell.backgroundColor = UIColor(white: 1, alpha: 0.5)
        }
    }
    
    3 回复  |  直到 8 年前
        1
  •  2
  •   vadian    8 年前

    首先,日期格式是错误的。必须是 "dd/MM/yy HH:mm:ss"

    最有效的解决方案“如果您负责JSON”发送 timestamp 作为 Double . 那就足够申报了 时间戳

    let timestamp: Date // UNIX format, eg. 1531294146340
    

    添加日期解码策略

    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .millisecondsSince1970
    

    另一种解决方案是将日期转换代码放入结构中

    struct News: Codable{
        let type: String
        let timestamp: String // UNIX format, eg. "1531294146340"
        let title: String
        let message: String
    
        enum  CodingKeys: String, CodingKey { case type, timestamp, title, message}
    
        let dateFormatter : DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateFormat = "dd/MM/yy HH:mm:ss"
            return formatter
        }()
    
        var dateString : String {
            let timeInterval = TimeInterval(timestamp)!
            let date = Date(timeIntervalSince1970: timeInterval / 1000)
            return dateFormatter.string(from:date)
        }
    }
    

    计算属性 dateString 包含日期字符串。


    你可以进一步申报 type 作为枚举

    enum Type : String, Codable {
        case organizational, planning
    }
    
    struct News: Codable{
        let type: Type
    ...
    
        2
  •  0
  •   kathayatnk    8 年前

    您应该能够将时间戳转换为日期,然后将其格式化为特定格式,并将其转换回字符串以显示在uilabel上。看看下面是否有帮助

    func string(from timestamp: String) -> String {
        if let timeInterval = TimeInterval(timestamp) {
            let date = Date(timeIntervalSince1970: timeInterval)
            let formatter = DateFormatter()
            formatter.dateFormat = "dd/MM/yy HH:mm:ss"
            return formatter.string(from: date)
        }
        return "" //return empty if somehow the timestamp conversion to TimeInterval (Double) fails
    } 
    
        3
  •  0
  •   ingconti    8 年前

    1)作为第一个建议,不要因为数字或原因而将日期存储为字符串。

    (苹果说要使用最基本的类型…所以使用64位作为unixtimestamp或nsdate。更为灵活,例如执行计算、差异、定位等…(而且更好的内存使用..(ints甚至不使用arc…)

    (并对字段使用可选选项…。更安全……)

    2)所以使用 延伸 保存为日期(例如)

    让我们从int unixtimestamp开始:

    (我为控制器添加了一个完整的示例…)

    //
    //  ViewController.swift
    //  sampleDate
    //
    //  Created by ing.conti on 16/08/2018.
    //  Copyright © 2018 com.ingconti. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //sample with int...
    
            if let dm =
                // Thursday, January 1, 2015 12:00:00 AM GMT+01:00
                (1420066800000/1000).fromUnixTimeStamp(){
                // note: usual timestamp from server come with milliseincods..
    
                //now You get a date... use and format!
                print(dm.description)
            }
    
            let testString = "1420066800"
            if let n = Int(testString), let dm = n.fromUnixTimeStamp(){
                    print(dm.description)
                }
            }
    
    }
    
    
    
    
    
    extension Int {
    
        func  fromUnixTimeStamp() -> Date? {
            let date = Date(timeIntervalSince1970: TimeInterval(self))
            return date
    }
    
    }
    

    所以请使用扩展名并更改您的使用日期。

    最后一点:Codable很好,但对于苹果在广告中所说的“边缘案例”并不好。 “反思”( https://developer.apple.com/swift/blog/?id=37 )有时候手工编写解析器更好…一小片JSON。

    例如,使用:

    (我重写了一点你的课…)

    typealias Dict = [String : Any]
    
    
    
    struct News{
        let type: String?
        // NO! let timestamp: String // UNIX format, eg. "1531294146340"
        let timestamp: Date?
        let title: String?
        let message: String?
    
    
        init?(dict : Dict?) {
    
            guard let d = dict else{
                return nil
            }
    
            if let s = d["timestamp"] as? String, let n = Int(s) {
                timestamp = n.fromUnixTimeStamp()
            }else{
                timestamp = nil // or other "default" ..
            }
    
            // go on parsing... other fields..
    
    
            if let s = d["type"] as? String{
                type = s
            }else{
                type = nil // or other "default" ..
            }
    
            if let s = d["title"] as? String {
                title = s
            }
            else{
                title = nil // or other "default" ..
            }
    
            if let s = d["message"] as? String {
                message = s
            }else{
                message = nil // or other "default" ..
            }
        }
    
    }
    

    所以用这种方法:

    let new = News(dict: dict)
    

    我通常用这种方式从JSON中提取数据:

    ...
    
          guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? Dict
                    else{
                        return
                }
    
                guard let dict = json else{
                    return
                }
    
    
    ..
            let new = News(dict: dict)