~pmikkelsen/dyalog-competition-2022

5b017359e18434255058f7c8b21a15a1d172307f — Peter Mikkelsen 2 years ago eb993b5
Save what I have in date.apln
1 files changed, 81 insertions(+), 0 deletions(-)

A date.apln
A date.apln => date.apln +81 -0
@@ 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