2015-10-16 34 views
2

所以在我的应用程序中,我需要处理日期,如\/Date(1440156888750-0700)\/,我认为第一部分代表从1970年1月1日开始的秒数,第二部分代表时区。 我不知道如何处理这样的数据,并使用Swift 2在Xcode 7中以大家都了解的方式显示它?如何将日期转换为/Date(1440156888750-0700) /为Swift可以处理的内容?

+0

您从哪里得到这个日期/字符串?此外,阅读[NSDate类参考](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/index.html)可能会帮助你。 – Arc676

+1

小修正,第一部分是从1970年开始* milli *秒。 – luk2302

回答

2

有点实验后围绕我想出了以下解决方案:

let dx = "/Date(1440156888750-0700)/" 
let timestamp = (dx as NSString).substringWithRange(NSRange(location: 6,length: 13)) 
let timezone = (dx as NSString).substringWithRange(NSRange(location: 19,length: 5)) 
let dateIntermediate = NSDate(timeIntervalSince1970: Double(timestamp)!/1000) 

let outp = NSDateFormatter() 
outp.dateFormat = "dd.MM.yyyy hh:mm::ssSSS" 
outp.timeZone = NSTimeZone(forSecondsFromGMT: 0) 

let input = outp.stringFromDate(dateIntermediate) + " " + timezone 
let inp = NSDateFormatter() 
inp.dateFormat = "dd.MM.yyyy hh:mm::ssSSS Z" 

let finalDate = inp.dateFromString(input) 
print(finalDate) 

让我解释一下:

  • 我们提取原始字符串毫秒时间戳和时区
  • 我们从时间戳创建一个日期,以便能够将其分成不同的组件
  • 我们以更标准的方式输出该日期(而不是时间戳)与先前提取的时区追加到该字符串
  • 我们再读取该字符串并从中重新分析日期


正如@ Phoen1xUK提到的时间戳可能有不同的长度超过13位数字。您可以通过删除/Date()/,然后在-(或+)之前拆分字符串来处理该情况。

+0

继续@ WhiteRice的问题,这是一个很好的答案,但是您对1970年以来的毫秒数(unix/posix/epoch时间),所以你不需要将时间戳除以1000. –

+0

@ Phoen1xUK我必须划分,因为时间间隔是秒,小数部分表示毫秒 – luk2302

+0

'NSTimeInterval总是在秒;它在10,000年的范围内产生亚毫秒的精度。' – luk2302

5

(这个答案的前一个版本实际上是错误的,它没有正确处理的时区。)

根据Stand-Alone JSON Serialization

DateTime值出现在表单JSON字符串“/ Date(700000 + 0500)/”,其中第一个数字(提供示例中为700000)是GMT时区中的毫秒数,即自1970年1月1日午夜以来的正常(非夏令时)时间。这个数字可能是负数,代表早些时候。示例中由“+0500”组成的部分是可选的,并指示时间为本地类型,即在反序列化时应转换为本地时区。如果它不存在,则将时间反序列化为Utc。实际数字(本例中为“0500”)及其符号(+或 - )被忽略。

Use JSON.NET to parse json date of format Date(epochTime-offset)

...在此[扭曲格式] [1]中,时间戳部分仍然只基于UTC。偏移量是额外信息。它不会更改时间戳。您可以给出不同的偏移量,或者完全忽略它,它仍然是相同的时间。

\/Date(1440156888750-0700)\/的第一个数字是 毫秒因为“时代” 1970年1月1日GMT时间 区部分-0700必须仅仅是忽略的数量,和。

这里是Date一个夫特3扩展方法,其检查 是字符串的有效性与正则表达式 (可接受\/Date(...)\//Date(...)/,有或没有 一个时区规范)并转换给定的数的 毫秒到Date

extension Date { 
    init?(jsonDate: String) { 

     let pattern = "\\\\?/Date\\((\\d+)(([+-]\\d{2})(\\d{2}))?\\)\\\\?/" 
     let regex = try! NSRegularExpression(pattern: pattern) 
     guard let match = regex.firstMatch(in: jsonDate, range: NSRange(location: 0, length: jsonDate.utf16.count)) else { 
      return nil 
     } 

     // Extract milliseconds: 
     let dateString = (jsonDate as NSString).substring(with: match.rangeAt(1)) 
     // Convert to UNIX timestamp in seconds: 
     let timeStamp = Double(dateString)!/1000.0 
     // Create Date from timestamp: 
     self.init(timeIntervalSince1970: timeStamp) 
    } 
} 

实施例:

let jsonDate = "\\/Date(1440156888750-0700)\\/" 
print("JSON Date:", jsonDate) 

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

输出:

 
JSON Date: \/Date(1440156888750-0700)\/ 
Date: 2015-08-21 11:34:48 +0000

更新斯威夫特4:

extension Date { 
    init?(jsonDate: String) { 

     let pattern = "\\\\?/Date\\((\\d+)(([+-]\\d{2})(\\d{2}))?\\)\\\\?/" 
     let regex = try! NSRegularExpression(pattern: pattern) 
     guard let match = regex.firstMatch(in: jsonDate, range: NSRange(jsonDate.startIndex..., in: jsonDate)) else { 
      return nil 
     } 

     // Extract milliseconds: 
     let dateString = jsonDate.substring(with: Range(match.range(at: 1), in: jsonDate)!) 
     // Convert to UNIX timestamp in seconds: 
     let timeStamp = Double(dateString)!/1000.0 
     // Create Date from timestamp: 
     self.init(timeIntervalSince1970: timeStamp) 
    } 
} 
+0

我想过这样的解决方案 - 只是从时间戳日期基于时区添加或删除TimeInterval,但我不喜欢这样的事实完全丢失原始字符串中存在的任何时区信息。 – luk2302

+0

@ luk2302:我不明白你的意思。 “+ -HHMM”转换为以秒为单位的时区偏移量以调整时间值。没有信息丢失。 –

+0

我的意思是返回格林威治标准时间的正确日期 - 是。但是你放弃了原始日期在不同时区给出的信息。最终输出中+0000表示的数值恰好 - 您在时区信息中丢失了-0700。 – luk2302