@@ 0,0 1,81 @@
+:Namespace date
+ DDN←{
+ info←13⍴⊂⍬ ⍝ The 13 fields from the variant table, without fractional seconds
+ info←⊃parse⍣≡info ⍺ ⍵ ⍝ Parse all we can
+ ⍝ At this point, we may not have all information, so we need to fix that
+ info←fixSecond fixMinute fixHour fixDay fixMonth fixYear info
+ 1⎕DT⊂,↑6↑info ⍝ convert the year, month, day, hour, minute, second to DDN
+ }
+ parse←{
+ (info format str)←⍵
+ str≡'':⍵
+ format startsWith⊂'YYYY':4(4000∘readNum)update 1⊢⍵
+ format startsWith⊂'YY':2(0 2000+99∘readNum)update 1⊢⍵
+ format startsWith'MMMM' 'Mmmm' 'mmmm' '_mmm':4(0∘readMonth)update 2⊢⍵
+ format startsWith'MMM' 'Mmm' 'mmm' '_mm':3(1∘readMonth)update 2⊢⍵
+ format startsWith'MM' '_M':2(12∘readNum)update 2⊢⍵
+ format startsWith⊂,'M':1(12∘readNum)update 2⊢⍵
+ format startsWith'DDDD' 'Dddd' 'dddd' '_ddd':4(0∘readDay)update 7⊢⍵
+ format startsWith'DDD' 'Ddd' 'ddd' '_dd':3(1∘readDay)update 7⊢⍵
+ format startsWith⊂,'d':1(7∘readNum)update 7⊢⍵
+ format startsWith'DD' '_D':2(31∘readNum)update 3⊢⍵
+ format startsWith⊂,'D':1(31∘readNum)update 3⊢⍵
+ format startsWith'hh' '_h':2(23∘readNum)update 4⊢⍵
+ format startsWith⊂,'h':1(23∘readNum)update 4⊢⍵
+ format startsWith'mm' '_m':2(59∘readNum)update 5⊢⍵
+ format startsWith⊂,'m':1(59∘readNum)update 5⊢⍵
+ format startsWith'ss' '_s':2(59∘readNum)update 6⊢⍵
+ format startsWith⊂,'s':1(59∘readNum)update 6⊢⍵
+ format startsWith'ww' '_w':2(53∘readNum)update 8⊢⍵
+ format startsWith⊂,'w':1(53∘readNum)update 8⊢⍵
+ format startsWith⊂'WWWW':4(4000∘readNum)update 9⊢⍵
+ format startsWith⊂'WW':2(4000∘readNum)update 9⊢⍵
+ format startsWith'yy' '_y':2(366∘readNum)update 10⊢⍵
+ format startsWith⊂,'y':1(366∘readNum)update 10⊢⍵
+ format startsWith'OO' 'Oo' 'oo':2{2,⎕C⊃⍵}update 11⊢⍵
+ format startsWith'O' 'o':1{1,⎕C⊃⍵}update 11⊢⍵
+ format startsWith'tt' '_t':2(12∘readNum)update 12⊢⍵
+ format startsWith⊂,'t':1(12∘readNum)update 12⊢⍵
+ format startsWith'PP' 'pp':2{2,⎕C⊃⍵}update 13⊢⍵
+ format startsWith'P' 'p':1{1,⎕C⊃⍵}update 13⊢⍵
+ 0⊣update 0⊢⍵
+ }
+ startsWith←{
+ ∨⌿⊃⍤⍷∘⍺¨⍵
+ }
+ update←{
+ (info format str)←⍵
+ ⍵⍵=0:info(1↓format)(1↓str) ⍝ Skip one char in both format and string
+ pattern←⍺↑format
+ (length value)←⍺⍺ str
+ info[⍵⍵]←value
+ info(⍺↓format)(length↓str)
+ }
+ ⍝ Below are all the "read" functions. They all return (value length) pairs
+ readNum←{
+ (valid n)←⎕VFI ⍵↑⍨maxLen←≢⍕⍺
+ valid∧n≤⍺:maxLen n
+ (¯1+10*maxLen-1)∇ ⍵
+ }
+ readMonth←{
+ months←'jan' 'feb' 'mar' 'apr' 'may' 'jun' 'jul' 'aug' 'sep' 'oct' 'nov' 'dec'
+ lengths←7 8 5 5 3 4 4 6 9 7 8 8
+ m←months⍳⊂⎕C 3↑⍵
+ ⍺:3 m ⍝ ⍺=1 means short form
+ lengths[m]m
+ }
+ readDay←{
+ days←'mon' 'tue' 'wed' 'thu' 'fri' 'sat' 'sun'
+ lengths←6 7 9 8 6 8 6
+ d←days⍳⊂⎕C 3↑⍵
+ ⍺:3 d ⍝ ⍺=1 means short form
+ lengths[d]d
+ }
+ ⍝ Below are all the fixup functions
+ fixYear←{}
+ fixMonth←{}
+ fixDay←{}
+ fixHour←{}
+ fixMinute←{}
+ fixSecond←{}
+:EndNamespace