Skip to content

Commit

Permalink
fix(ISO8601): comma-spec'd decimal seconds (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
rsk0 committed Jun 19, 2023
1 parent e5d38bb commit e309741
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 24 deletions.
53 changes: 32 additions & 21 deletions spec/date_spec.lua
Expand Up @@ -20,43 +20,54 @@ describe("Testing the 'date' module", function()
assert(date("Jul 27 2006 MDT") == date(2006,07,27,6,0,0))
assert(date("Jul 27 2006 PST") == date(2006,07,27,8,0,0))
assert(date("Jul 27 2006 PDT") == date(2006,07,27,7,0,0))
-- Date Format. Short dates can use either a "/" or "-" date separator,
-- but must follow the month/day/year format
-- Date Format. Short dates can use either a "/" or "-" date separator, but must
-- follow the month/day/year format.
assert(date("02-03-04")==date(1904,02,03))
assert(date("12/25/98")==date(1998,12,25))
-- Long dates of the form "July 10 1995" can be given with the year, month,
-- and day in any order, and the year in 2-digit or 4-digit form. If you use
-- the 2-digit form, the year must be greater than or equal to 70.
-- Long dates of the form "July 10 1995" can be given with the year, month, and day
-- in any order, and the year in 2-digit or 4-digit form. If you use the 2-digit
-- form, the year must be greater than or equal to 70.
assert(date("Feb-03-04")==date(1904,02,03))
assert(date("December 25 1998")==date(1998,12,25))
-- Follow the year with BC or BCE to indicate that the year is before common era.
assert(date("Feb 3 0003 BC")==date(-2,02,03))
assert(date("December 25 0001 BC")==date(0,12,25))

-- Supported ISO 8601 Formats.
-- YYYY-MM-DDwhere YYYY is the year, MM is the month of the year, and DD is the
-- day of the month.
-- Supported ISO 8601 Formats
-- YYYY-MM-DD, where YYYY is the year, MM is the month of the year, and DD is the
-- day of the month
assert(date("2000-12-31")==date(2000,12,31))
assert(date(" 20001231 ")==date(2000,12,31)) -- Compact version
-- YYYY-DDDwhere YYYY is the year, DDD is the day of the year.
assert(date(" 20001231 ")==date(2000,12,31)) -- "basic format" (compact)
-- YYYY-DDD, where YYYY is the year, DDD is the day of the year
assert(date("1995-035")==date(1995,02,04))
assert(date("1995035 ")==date(1995,02,04)) -- Compact version
-- YYYY-WDD-Dwhere YYYY is the year, DD is the week of the year, D is the day of
-- the week.
assert(date("1995035 ")==date(1995,02,04)) -- "basic format" (compact)
-- YYYY-WDD-D, where YYYY is the year, DD is the week of the year, D is the day of
-- the week
assert(date("1997-W01-1")==date(1996,12,30))
assert(date(" 1997W017")==date(1997,01,05)) -- Compact version
-- DATE HH:MM:SS.SSSWhere DATE is the date format discuss above, HH is the hour,
-- MM is the miute, SS.SSS is the seconds (fraction is optional).
assert(date(" 1997W017")==date(1997,01,05)) -- "basic format" (compact)
-- DATE HH:MM:SS.SSS, where DATE is the date format discussed above, HH is the hour,
-- MM is the minute, SS.SSS is the seconds (fraction is optional)
-- These are not ISO 8601 conformant: Space between date and time is no longer
-- allowed (though is in RFC 3339).
assert(date("1995-02-04 24:00:51.536")==date(1995,2,5,0,0,51.536))
assert(date("1995-02-04 24:00:51,536")==date(1995,2,5,0,0,51.536))
assert(date("1976-W01-1 12:12:12.123")==date(1975,12,29,12,12,12.123))
assert(date("1995-035 23:59:59.99999")==date(1995,02,04,23,59,59.99999))
-- Compact version separated by latin capital letter T
-- "basic format" (compact), date and time separated by the Latin capital T
assert(date(" 19950205T000051.536 ")==date(1995,2,5,0,0,51.536))
assert(date(" 19950205T000051,536 ")==date(1995,2,5,0,0,51.536))
assert(date(" 1976W011T121212.123 ")==date(1975,12,29,12,12,12.123))
assert(date(" 1995035T235959.99999 ")==date(1995,02,04,23,59,59.99999))
-- DATE TIME +HH:MM, DATE TIME -HHMM, DATE TIME Z,Where DATE and TIME is the date
-- and time format discuss above. First character is a sign "+" (east of UTC) or "-"
-- (west of UTC). HH and MM is Hours and minutes offset. The Z stands for the zero offset.
assert(date(" 1995035T235959.99999 ")==date(1995,02,04,23,59,59.99999)) -- not ISO 8601 conformant day spec
-- "extended format" (human readable), date and time separated by the Latin
-- capital T
assert(date("1995-02-05T00:00:51.536")==date(1995,2,5,0,0,51.536))
assert(date("1995-02-05T00:00:51,536")==date(1995,2,5,0,0,51.536))
assert(date("1976-W01-1T12:12:12.123")==date(1975,12,29,12,12,12.123))
assert(date("1995-035T23:59:59.99999")==date(1995,02,04,23,59,59.99999)) -- not ISO 8601 conformant day spec
-- DATE TIME +HH:MM, DATE TIME -HHMM, DATE TIME Z, where DATE and TIME is the date
-- and time format discussed above
-- First character is a sign "+" (east of UTC) or "-" (west of UTC). HH and MM are
-- hours and minutes offset. The Z stands for the zero offset.
assert(date("1976-W01-1 12:00Z ")==date(1975,12,29,12))
assert(date("1976-W01-1 13:00+01:00")==date(1975,12,29,12))
assert(date("1976-W01-1 0700-0500 ")==date(1975,12,29,12))
Expand Down
6 changes: 3 additions & 3 deletions src/date.lua
Expand Up @@ -314,21 +314,21 @@
local function seth(q) h = h and error_dup() or tonumber(q) end
local function setr(q) r = r and error_dup() or tonumber(q) end
local function sets(q) s = s and error_dup() or tonumber(q) end
local function adds(q) s = s + tonumber(q) end
local function adds(q) s = s + tonumber("."..string.sub(q,2,-1)) end
local function setj(q) j = (m or w or j) and error_dup() or tonumber(q); end
local function setz(q) z = (z ~= 0 and z) and error_dup() or q end
local function setzn(zs,zn) zn = tonumber(zn); setz( ((zn<24) and (zn*60) or (mod(zn,100) + floor(zn/100) * 60))*( zs=='+' and -1 or 1) ) end
local function setzc(zs,zh,zm) setz( ((tonumber(zh)*60) + tonumber(zm))*( zs=='+' and -1 or 1) ) end

if not (sw("^(%d%d%d%d)",sety) and (sw("^(%-?)(%d%d)%1(%d%d)",function(_,a,b) setm(tonumber(a)); setd(tonumber(b)) end) or sw("^(%-?)[Ww](%d%d)%1(%d?)",function(_,a,b) w, u = tonumber(a), tonumber(b or 1) end) or sw("^%-?(%d%d%d)",setj) or sw("^%-?(%d%d)",function(a) setm(a);setd(1) end))
and ((sw("^%s*[Tt]?(%d%d):?",seth) and sw("^(%d%d):?",setr) and sw("^(%d%d)",sets) and sw("^(%.%d+)",adds))
and ((sw("^%s*[Tt]?(%d%d):?",seth) and sw("^(%d%d):?",setr) and sw("^(%d%d)",sets) and sw("^([,%.]%d+)",adds))
or sw:finish() or (sw"^%s*$" or sw"^%s*[Zz]%s*$" or sw("^%s-([%+%-])(%d%d):?(%d%d)%s*$",setzc) or sw("^%s*([%+%-])(%d%d)%s*$",setzn))
) )
then --print(y,m,d,h,r,s,z,w,u,j)
sw:restart(); y,m,d,h,r,s,z,w,u,j = nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
repeat -- print(sw:aimchr())
if sw("^[tT:]?%s*(%d%d?):",seth) then --print("$Time")
_ = sw("^%s*(%d%d?)",setr) and sw("^%s*:%s*(%d%d?)",sets) and sw("^(%.%d+)",adds)
_ = sw("^%s*(%d%d?)",setr) and sw("^%s*:%s*(%d%d?)",sets) and sw("^([,%.]%d+)",adds)
elseif sw("^(%d+)[/\\%s,-]?%s*") then --print("$Digits")
x, c = tonumber(sw[1]), len(sw[1])
if (x >= 70) or (m and d and (not y)) or (c > 3) then
Expand Down

0 comments on commit e309741

Please sign in to comment.