将JSON(日期)解析为Swift

6

我在我的Swift应用程序中使用了一个返回JSON,并且其中有一个字段返回了一个日期。当我引用此数据时,代码给我返回一个类似于“/Date(1420420409680)/”这样的东西。我该如何将其转换为NSDate?请使用Swift进行操作,我已经尝试过Objective-C的示例,但没有成功。


1
请访问以下链接:https://dev59.com/1l8d5IYBdhLWcg3waxro。 - rmaddy
这是一个简单的 UNIX 时间戳。 - Hot Licks
@HotLicks:...只有毫秒(否则将是在公元46981年 :) - Martin R
@MartinR - 是的,你可以通过前导的“14”来识别它,然后你必须通过计算数字来确定它是秒、毫秒还是微秒。(在我遇到的一个案例中,甚至是10纳秒。) - Hot Licks
3个回答

10

看起来非常类似于Microsoft的ASP.NET AJAX使用的日期JSON编码,该编码在JavaScript和.NET中介绍了JavaScript对象表示法(JSON)的入门

例如,Microsoft的ASP.NET AJAX不使用描述的任何一种约定。相反,它将.NET DateTime值编码为JSON字符串,其中字符串的内容为/Date (ticks)/,而ticks表示自纪元(UTC)以来的毫秒数。因此,1989年11月29日上午4点55分30秒(UTC)被编码为“\/Date (628318530718)\/”。

唯一的区别是您有格式/Date(ticks)/而不是\/Date(ticks)\/

您必须提取括号内的数字。将该数字除以1000即可得到自1970年1月1日以来的秒数。

以下代码显示了如何执行此操作。它作为NSDate的“可失败便利初始化程序”实现:

extension NSDate {
    convenience init?(jsonDate: String) {

        let prefix = "/Date("
        let suffix = ")/"
        // Check for correct format:
        if jsonDate.hasPrefix(prefix) && jsonDate.hasSuffix(suffix) {
            // Extract the number as a string:
            let from = jsonDate.startIndex.advancedBy(prefix.characters.count)
            let to = jsonDate.endIndex.advancedBy(-suffix.characters.count)
            // Convert milliseconds to double
            guard let milliSeconds = Double(jsonDate[from ..< to]) else {
                return nil
            }
            // Create NSDate with this UNIX timestamp
            self.init(timeIntervalSince1970: milliSeconds/1000.0)
        } else {
            return nil
        }
    }
}

示例用法 (使用您的日期字符串):

if let theDate = NSDate(jsonDate: "/Date(1420420409680)/") {
    print(theDate)
} else {
    print("wrong format")
}

这将输出

2015-01-05 01:13:29 +0000

针对Swift 3的更新(Xcode 8):

extension Date {
    init?(jsonDate: String) {

        let prefix = "/Date("
        let suffix = ")/"

        // Check for correct format:
        guard jsonDate.hasPrefix(prefix) && jsonDate.hasSuffix(suffix) else { return nil }

        // Extract the number as a string:
        let from = jsonDate.index(jsonDate.startIndex, offsetBy: prefix.characters.count)
        let to = jsonDate.index(jsonDate.endIndex, offsetBy: -suffix.characters.count)

        // Convert milliseconds to double
        guard let milliSeconds = Double(jsonDate[from ..< to]) else { return nil }

        // Create NSDate with this UNIX timestamp
        self.init(timeIntervalSince1970: milliSeconds/1000.0)
    }
}

示例:

if let theDate = Date(jsonDate: "/Date(1420420409680)/") {
    print(theDate)
} else {
    print("wrong format")
}

@Martin,这个扩展对于像“/Date(1479119050805+0300)/”这样的值会失败,因为毫秒的Double init方法无法返回一个双精度浮点数,以处理1479119050805+0300的加号。如果您成功处理了这种情况,请在此分享您的代码。 - JAHelia
1
@JAHelia:请看一下https://dev59.com/V5Dea4cB1Zd3GeqPXycP#33166980,这是一个更新的版本,可以读取带或不带时区偏移量的JSON日期。 - Martin R

2
在其他人提供的内容之上,只需在您的类中创建以下实用方法即可:
  func dateFromStringConverter(date: String)-> NSDate? {
    //Create Date Formatter
    let dateFormatter = NSDateFormatter()
    //Specify Format of String to Parse
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" //or you can use "yyyy-MM-dd'T'HH:mm:ssX"
    //Parse into NSDate
    let dateFromString : NSDate = dateFormatter.dateFromString(date)!

    return dateFromString
}

然后,您可以在成功返回和解析的JSON对象中调用此方法,如下所示:
//Parse the date
 guard let datePhotoWasTaken = itemDictionary["date_taken"] as? String else {return}
     YourClassModel.dateTakenProperty = self.dateFromStringConverter(datePhotoWasTaken)

或者您可以完全忽略上面的实用程序方法和调用者代码,直接执行以下操作:

//Parse the date
 guard let datePhotoWasTaken = itemDictionary["date_taken"] as? NSString else {return}
     YourClassModel.dateTakenProperty = NSDate(timeIntervalSince1970: datePhotoWasTaken.doubleValue)

那应该可以工作!


1
问题是关于解析类似于"/Date(1420420409680)/"的字符串。 - Martin R

0

看起来像 UNIX 时间戳:01/12/2015 @ 6:14pm (UTC) [根据 http://www.unixtimestamp.com/index.php ]

您可以使用构造函数 NSDate(timeIntervalSince1970: unixTimestamp) 将其转换为 NSDate 对象。


这个变量的时间跨度怎么获取? - Aretha Freitas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接