简体   繁体   English

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

[英]Convert UNIX time from json import (swift struct) to date as string and populate table

I have a json file being imported to my project ( https://api.myjson.com/bins/ywv0k ). 我有一个导入到我的项目中的json文件( https://api.myjson.com/bins/ywv0k )。 The json attributes are decoded and stored in my struct class "News", which has the same attributes like the json file. json属性被解码并存储在结构类“ News”中,该结构类具有与json文件相同的属性。

in a second step I populate a table with the string attribute "timestamp" from my struct class "News", which is actually a UNIX time. 在第二步中,我从结构类“ News”中填充带有字符串属性“ timestamp”的表,这实际上是UNIX时间。

My problem now is that I am lost how to change this UNIX time to a string of format "dd/mm/yy HH:mm:ss", since I get an error when I try to put a function 我现在的问题是我迷失了如何将此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)

into the do-encoding-loop as well as when I put it into this table function: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell. 进入do-encoding-loop以及将其放入此表函数时:func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell。

Swift 4 斯威夫特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)
    }
}

First of all the date format is wrong. 首先日期格式错误。 It has to be "dd/MM/yy HH:mm:ss" 必须为"dd/MM/yy HH:mm:ss"

The most efficient solution – if you are responsible for the JSON – send the value for timestamp as Double . 如果您负责JSON,则最有效的解决方案是将timestamp的值发送为Double Then it's sufficient to declare timestamp 然后就足够声明timestamp

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

and add the date decoding strategy 并添加日期解码策略

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

Another solution is to put the date conversion code into the struct 另一个解决方案是将日期转换代码放入struct

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)
    }
}

The computed property dateString contains the date string. 计算的属性dateString包含日期字符串。


Further you could declare type as enum 此外,您可以将type声明为枚举

enum Type : String, Codable {
    case organizational, planning
}

struct News: Codable{
    let type: Type
...

You should be able to convert the timestamp to date and then format it to specific format and convert back to String to display on UILabel. 您应该能够将时间戳转换为日期,然后将其格式化为特定格式,然后转换回String以显示在UILabel上。 See if the following helps 查看以下内容是否有帮助

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
} 

1) As a first suggestion, do NOT store date as string for a number or reasons. 1)作为第一个建议,不要出于任何原因将日期存储为字符串。

(Apple says to use the very basic type... so use a 64bit for UnixTimestamp OR NSDate.. far more flexible, for example performing calcs, difference, localisations and so on... (and far better memory usage.. (Ints do not even use ARC...)) (Apple表示使用非常基本的类型...因此,对于UnixTimestamp或NSDate使用64位。.更加灵活,例如执行计算,差异,本地化等等...(以及更好的内存使用。.(Ints甚至不使用ARC ...))

(and use optional for fields.... far more secure..) (并且对字段使用可选。...更加安全。)

2) so use an extension to save as Date (for example) 2)因此,请使用扩展名另存为日期(例如)

Let's start from a int unixTimestamp: 让我们从一个int unixTimestamp开始:

(I added a complete sample for a controller...) (我为控制器添加了完整的示例...)

//
//  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
}

}

so use extension AND change your to use date. 因此请使用扩展名并更改您的使用日期。

A final note: codable is fine, but not fine for "edge cases"ad apple says in "Reflecting on Reflection" ( https://developer.apple.com/swift/blog/?id=37 ) sometimes is better to write parser by hand... for a small piece of JSON. 最后一点:codable很好,但不适用于“边缘情况”,苹果在“ Reflecting on Reflection”( https://developer.apple.com/swift/blog/?id=37 )中说,有时写得更好手动解析器...用于一小段JSON。

So for example use: 因此,例如使用:

(I rewrote a bit your class...) (我改写了你的课...)

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" ..
        }
    }

}

so use in this way: 因此以这种方式使用:

... ...

let new = News(dict: dict)

I usually extract data form JSON in this way: 我通常以这种方式提取数据形式的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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM