2011-10-27 18 views
8

Lua'daki JSON verilerinden tam bir ISO8601 tarihini ayrıştırmaya çalışıyorum. Eşleşme düzeninde sorun yaşıyorum. - veya + veya hiçbiriLua ISO 8601 datetime ayrıştırma modeli

-- Example datetime string 2011-10-25T00:29:55.503-04:00 
local datetime = "2011-10-25T00:29:55.503-04:00" 
local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)%.(%d+)" 
local xyear, xmonth, xday, xhour, xminute, 
     xseconds, xmillies, xoffset = datetime:match(pattern) 

local convertedTimestamp = os.time({year = xyear, month = xmonth, 
     day = xday, hour = xhour, min = xminute, sec = xseconds}) 

orada hiçbir mantıklı olan veya idare edecek çünkü desen üzerinde diliminin nasıl başa de şaşırıp:

Şimdiye kadar, bu ben ne var. Ancak, lua'nın os.time işlevindeki saat dilimini desteklemediğini bilmeme rağmen, en azından nasıl ayarlanması gerektiğini bilirim.

"." (milisaniye ve saat dilimi), ama sonra gerçekten geçerli bir tarih olmayacaktı. Milisaniye o kadar önemli değil ve onu kaybetmemek istemem ama zaman dilimi işleri değiştiriyor.

Not: Biri Bunu yapmak için bazı çok daha iyi kod sahip olabilir ve ben buna evli değilim, ben sadece datetime dize :)

+0

BTW kikito'nun yanıtı iyi; sadece bir not: tarih/zaman ayırmak için '' (uzay) yanı sıra 'T' kabul etmek için iyi bir hamle olabilir, çünkü pek çok kişi ve araç ISO tarzı tarih-kez yazıyor (belki de 'T' kullanın!). – snogglethorpe

+0

Bu işaretçi için teşekkürler. Benim durumumda, bu konuda çok fazla endişelenmem gerekmiyor çünkü örüntü biliniyor: 2011-10-25T00: 29: 55.503-04: 00 –

cevap

10

tam ISO 8601 biçiminde olabilir' dışında işe yarar bir şey almak gerekir Tek bir desen eşleşmesi ile yapılmamalıdır. Çok fazla varyasyon var.

bazı örnekler from the wikipedia page: YYYYMMDD gün omited edilebilir

  • YYYY-MM-DD vs:

    • değil ayrı numaralar yapan bir "sıkıştırılmış" biçimi yoktur YYYY-MM-DD ve YYYY-MM her ikisi de geçerli tarihlerdir
    • Ordinal tarih de geçerlidir: DDDYYYY-DDD, yılın günüdür (1-365/6)
    • t hh:mm:ss, hh:mm ve hh
    • Üstelik
    • , zamanı da sıkıştırılmış sürüme sahip tüm geçerli zamanlardır: ime, dakika ve saniye ommited edilebilir hhmmss
    • Ve bunun üzerine hhmm, zaman kullanarak, kesirler kabul hem zaman dilimindeki alt zaman elemanının kesirlerini belirtmek için nokta veya virgül. 14:30,5,, 14:30.5, veya 1430.5 hepsi 14 saat, 30 saniye ve bir buçuk temsil eder.
    • Son olarak, saat dilimi bölümü isteğe bağlıdır. Mevcut olduğunda, bu Z harfi, ±hh:mm, ±hh veya ±hhmm olabilir.

    Bu nedenle, tüm özelliklere göre ayrıştırılacaksanız dikkate alınması gereken birçok istisna vardır.

    function parseDateTime(str) 
        local Y,M,D = parseDate(str) 
        local h,m,s = parseTime(str) 
        local oh,om = parseOffset(str) 
        return os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}) 
    end 
    

    Ve sonra parseDate, parseTime ve parseOffset oluşturması gerekecektir: Bu durumda, ilk kod aşağıdaki gibi görünebilir. Daha sonra zaman ofsetleri UTC'den döndürmeli, ilk ikisi sıkıştırılmış formatlar, zaman dilimleri, virgül veya nokta ayırıcıları ve benzerleri gibi şeyleri hesaba katmak zorunda kalacaktı. karakteri, desen eşleşmelerinin başlangıcında, tarihin dizenin başında olması gerektiğinden, büyük olasılıkla "^" karakterini kullanır.parseTime 'in desenleri muhtemelen "T" ile başlayacaktır. Ve parseOffset 'lar "$" ile bitecek, çünkü zaman ofsetleri, bulunduklarında, sonunda.

    Bir "tam ISO" parseOffset fonksiyonu buna benzer görünebilir:

    function parseOffset(str) 
        if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time 
    
        -- matches ±hh:mm, ±hhmm or ±hh; else returns nils 
        local sign, oh, om = str:match("([-+])(%d%d):?(%d?%d?)$") 
        sign, oh, om = sign or "+", oh or "00", om or "00" 
    
        return tonumber(sign .. oh), tonumber(sign .. om) 
    end 
    

    arada, bilgisayarınızın UTC zamanı çalıştığını tahmin ediyorum. Eğer durum böyle değilse, bunun hesaplanması için saatleriniz/dakikalarınızda ek bir mahsup eklemeniz gerekecektir.

    function parseDateTime(str) 
        local Y,M,D = parseDate(str) 
        local h,m,s = parseTime(str) 
        local oh,om = parseOffset(str) 
        local loh,lom = getLocalUTCOffset() 
        return os.time({year=Y, month=M, day=D, hour=(h+oh-loh), min=(m+om-lom), sec=s}) 
    end 
    

    yerel Eğer http://lua-users.org/wiki/TimeZone bakmak isteyebilirsiniz ofset almak için.

    Umarım bu yardımcı olur. Saygılarımızla!

  • +0

    Bazı avantajlarım var çünkü formatın sunucuda ne olacağını biliyorum. Ancak, ben Lua daha iyi paketi değiştirmek istemedim, çünkü diğer istemciler daha sonra sorunları olabilir. –

    +0

    Saatin saat dilimi ofseti yanlış. GMT'de doğru saati bulmak için saatten çıkarılması gerekiyor. – CanSpice

    +0

    @CanSpice Teşekkürler, sabit! – kikito

    İlgili konular