2011-10-27 5 views
8

루아의 JSON 데이터로부터 전체 ISO8601 datetime을 파싱하려고합니다. 일치 패턴에 문제가 있습니다. - 또는 + 또는 아무도루아 ISO 8601 datetime 파싱 패턴

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

내가 거기에 논리적 없습니다 또는 처리하지 않는 때문에 패턴에 시간대를 처리하는 방법에 붙어 :

지금까지이 내가 가진 것입니다. lua가 os.time 함수에서 시간대를 지원하지 않는다는 것을 알고 있지만 적어도 조정할 필요가 있다는 것을 알고 있습니다.

나는 "." (밀리 초 및 시간대),하지만 난 정말 유효한 datetime이 없을거야. 밀리 초는 그다지 중요하지 않으며 잃어 버릴 염려는 없지만 시간대가 바뀝니다.

참고 : 누군가는이 일을 몇 가지 더 나은 코드를 가질 수 있으며, 내가 결혼 아니에요, 난 그냥 날짜 문자열 :

+0

BTW kikito의 대답은 좋습니다; 많은 메모와 많은 도구들이 ISO 스타일의 날짜 - 시간을 그런 식으로 작성하기 때문에 날짜/시간을 구분하기 위해 'T'뿐만 아니라 '(공백)을 받아들이는 것이 좋을지도 모른다. 'T'를 사용하십시오!). – snogglethorpe

+0

그 포인터 주셔서 감사. 내 경우에는 패턴이 너무 많아 걱정할 필요가 없습니다. 2011-10-25T00 : 29 : 55.503-04 : 00 –

답변

10

전체 ISO 8601 형식이 수 '에서 유용한 무언가를 얻을 필요 단일 패턴 매치로 끝내야합니다. 너무 많은 변형이 있습니다.

몇 가지 예 from the wikipedia page : YYYYMMDD 날이 omited 할 수

  • YYYY-MM-DD 대 :

    • 이 아닌 별도의 번호를 수행하는 "압축"형식이 YYYY-MM-DDYYYY-MM 모두 유효한 날짜입니다
    • 서수 날짜도 유효합니다. YYYY-DDD 여기서 DDD은 일 (1-365/6)입니다.
    • t hh:mm:ss, hh:mmhh
    • 또한
    • 이 시간은 또한 압축 된 버전은 모든 유효한 배 : IME는 분 및 초 ommited 될 수 hhmmss
    • 그리고 그 위에 hhmm은 시간은 사용 을 분획을 받아 둘 시간 부분에 더 낮은 시간 요소의 분수를 나타내는 점 또는 쉼표. 14:30,5, 1430,5, 14:30.5 또는 1430.5은 모두 14 시간 30 초 반을 나타냅니다.
    • 마지막으로, 시간대 섹션은 선택 사항입니다. 문자가있는 경우 문자 Z, ±hh:mm, ±hh 또는 ±hhmm이 될 수 있습니다.

    전체 사양에 따라 구문 분석 할 경우 고려해야 할 예외가 많이 있습니다.

    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 
    

    을 그리고 당신은 parseDate, parseTimeparseOffset을 만들어야 할 것입니다 :이 경우, 초기 코드는 다음과 같을 수 있습니다. 나중에는 UTC의 시간 오프셋을 반환해야하며 처음 두 개는 압축 된 형식, 시간 분수, 쉼표 또는 점 분리 기호 등과 같은 사항을 고려해야합니다.

    parseDate은 패턴 일치 시작 부분에문자를 사용할 가능성이 있습니다. 그 이유는 날짜가 문자열의 시작 부분에 있어야하기 때문입니다.parseTime 님의 패턴은 "T"으로 시작합니다. 그리고 parseOffset"$"으로 끝날 것입니다. 시간 오프셋은 존재할 때 마지막에 있기 때문입니다.

    A "전체 ISO"parseOffset 기능이 유사 있습니다

    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 
    

    을 그건 그렇고, 당신의 컴퓨터가 UTC 시간에 작동하고 있음을 가정하고있다. 그렇지 않은 경우에는이를 고려하여 시간당 몇 분의 오프셋을 추가해야합니다.

    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 
    

    로컬 오프셋을 얻으려면 http://lua-users.org/wiki/TimeZone을 참조하십시오.

    이 정보가 도움이되기를 바랍니다. 문안 인사!

  • +0

    서버에서 어떤 형식이 될지 알고 있기 때문에 이점이 있습니다. 그러나 다른 클라이언트가 문제를 가질 수 있기 때문에 Lua를 더 잘 변경하려고하지 않았습니다. –

    +0

    시간대의 시간대 오프셋이 잘못되었습니다. 그리니치 표준시로 정확한 시간을 얻으려면 시간에서 빼야합니다. – CanSpice

    +0

    @CanSpice 고마워, 고쳐! – kikito

    1

    iso8601을 지원하는 luadate 패키지도 있습니다. (당신은 아마도 patched version을 원할 것입니다)

    관련 문제