ios formatters Como converter data como \/Date(1440156888750-0700) \/para algo que o Swift pode manipular?




nsdate format (2)

então no meu aplicativo, eu preciso lidar com a data como \/Date(1440156888750-0700)\/ , acho que a primeira parte representa os segundos de 1 de janeiro de 1970 e a segunda parte é o fuso horário. Eu não sei como lidar com dados como este e exibi-lo da maneira que todos nós entendemos no Xcode 7 usando o Swift 2?


Answer #1

(A versão anterior dessa resposta estava errada, não lidava corretamente com o fuso horário.)

De acordo com a serialização JSON autônoma :

Os valores DateTime aparecem como strings JSON na forma de "/ Date (700000 + 0500) /", onde o primeiro número (700000 no exemplo fornecido) é o número de milissegundos no fuso horário GMT, regular (sem horário de verão) tempo desde a meia-noite de 1 de janeiro de 1970. O número pode ser negativo para representar tempos mais antigos. A parte que consiste em "+0500" no exemplo é opcional e indica que a hora é do tipo Local - isto é, deve ser convertida para o fuso horário local na desserialização. Se estiver ausente, o tempo é desserializado como Utc. O número real ("0500" neste exemplo) e seu sinal (+ ou -) são ignorados.

e Use JSON.NET para analisar a data json do formato Data (epochTime-offset)

... Neste [formato de parafuso] [1], a parte do registro de data e hora ainda é baseada somente no UTC. O deslocamento é uma informação extra . Não muda o timestamp. Você pode dar um offset diferente ou omiti-lo completamente e ainda é o mesmo momento no tempo.

o primeiro número em \/Date(1440156888750-0700)\/ é o número de milissegundos desde o "epoch" 1 de janeiro de 1970 GMT, e o fuso horário parte -0700 deve ser simplesmente ignorado.

Aqui está um método de extensão do Swift 5 para Date que verifica a validade da string com uma expressão regular (aceitando ambas as expressões \/Date(...)\/ e /Date(...)/ , com ou sem uma especificação de fuso horário ) e converte o dado número de milissegundos em uma Date :

extension Date {
    init?(jsonDate: String) {

        let pattern = #"\\?/Date\((\d+)([+-]\d{4})?\)\\?/"#
        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[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)
    }
}

Exemplo:

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

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

Saída:

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

(Versões para Swift 3 e Swift 4 podem ser encontradas no histórico de edição.)


Answer #2

Depois de experimentar um pouco, encontrei a seguinte solução:

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)

Deixe-me explicar:

  • extraímos o timestamp de milissegundos e o fuso horário da string original
  • criamos uma data a partir do timestamp para poder dividi-la em seus diferentes componentes
  • nós produzimos essa data de uma maneira mais padrão (não como timestamp) e anexamos o fuso horário previamente extraído àquela string
  • nós então lemos essa string e analisamos uma data dela novamente

Nota
Como @ Phoen1xUK mencionou o timestamp pode ter um comprimento diferente de 13 dígitos. Você pode lidar com essa situação removendo /Date( e )/ e dividindo a string antes de - (ou + ).





date