There are different ways to represent dates. No one way is satisfactory for all purposes. DateTime objects work well for most, if you do not have too many of them. When you do, you will want other representations, according to what you need to get done.

DateTime objects

A .Net DateTime object displays in readable form, and supports the comparison functions and also addition and subtraction. You can include them in arrays with other kinds of data. They have to be serialised to be stored, but that is little trouble when they can represent themselves as readable strings and be as easily reinstantiated from them.

Here are some examples of handling dates as DateTime objects.

      ⎕USING←'System'
      +dt←DateTime.Now             ⍝ displays readably
07/01/2008 16:56:50

      ⍴⍴dt                         ⍝ but is scalar
0

      ⍴dt.⎕NL-2 3                  ⍝ has many properties and methods
59

      ⍴⎕←dt.ToShortDateString      ⍝ represent as character vector
07/01/2008
10

The class offers many useful methods.

      dt.IsDaylightSavingTime
0
      DateTime.Parse∘⊂¨'15/9/52' '15SEP52' '15 September 1952'
 15/09/1952 00:00:00  15/09/1952 00:00:00  15/09/1952 00:00:00
      DateTime.IsLeapYear 2007
0
      DateTime.DaysInMonth¨(2007 2)(2008 2)
28 29

Comparison functions extend to the objects.

      +bd←DateTime.New 1952 9 15   ⍝ SJT’s birthday
15/09/1952 00:00:00

      ⍝ and now his whole family
      ∆←('mum' 1930 5 24)('dad' 1926 9 3)
      ∆,←('caro' 1960 11 16)('jo' 1954 7 5)('me' 1952 9 15)
      +fmly←↑{⍵[1],DateTime.New 1↓⍵}¨∆
 mum   24/05/1930 00:00:00
 dad   03/09/1926 00:00:00
 caro  16/11/1960 00:00:00
 jo    05/07/1954 00:00:00
 me    15/09/1952 00:00:00

      ⊃∘⊃∘⎕CLASS¨fmly[;2]          ⍝ 2nd column contains DateTime objects
 System.DateTime  System.DateTime  System.DateTime  System.DateTime  …

      {⍎⍺,'←⍵'}/fmly               ⍝ associate names and dates

      mum=dad                      ⍝ equivalence
0
      fmly[;2]⍳jo caro             ⍝ lookup
4 3
      mum⌊dad                      ⍝ comparison
03/09/1926 00:00:00
      fmly[⍋fmly[;2];1]            ⍝ names in birth order
 dad  mum  me  jo  caro

Subtraction extends to the objects, returning TimeSpan objects.

      mum-dad                      ⍝ days between my parents' births
1359.00:00:00
      ⊃⊃⎕CLASS mum-dad
System.TimeSpan
      (2-/caro jo me mum dad).Days ⍝ days between all our births
2326 658 8150 1359

For modest amounts of data it is hard to improve on the versatility of DateTime objects.

The obvious limit to this strategy is the number of DateTime objects you create and destroy. When handling large tables and vectors you might need to find lighter, faster ways to handle dates.

That is what this section is about.

Other formats


Some simple techniques for working with dates.

Addition and subtraction on dates are conveniently performed as IDN numbers. The root functions DateToIDN and IDNToDate are fast and handy:

      -/DateToIDN¨(1954 7 5)(1952 9 15) ⍝ days between my and my sister's births
658

But we'll get tired of seeing them everywhere. So let's have an operator.

      asIDN←{IDNToDate ⍺ ⍺⍺ DateToIDN ⍵}
      7 -⍨ asIDN 1954 7 5 ⍝ 1 week before my sister's birthday
1954 6 28 0

Scalars are often more convenient than triples. We can use ⊥ and ⊤ to switch representations.

      100⊥1954 7 5
19540705
      0 100 100⊤19540705
1954 7 5
      (100⊥⍣¯1)19540705
1954 7 5
      dual←{⍺(⍺⍺⍣¯1)⍵⍵ ⍺ ⍺⍺ ⍵}
      0 100 100⊤dual {⎕←⍵} 19540705                           ⍝ display before recoding
1954 7 5
19540705
      0 100 100⊤dual {⎕←⍵} 19540705 19520915                  ⍝ my and my sister's birthdates
1954 1952
   7    9
   5   15
19540705 19520915
      0 100 100⊤dual {⎕←⍵} 20070714 19520915                  ⍝ today and my birthdate
2007 1952
   7    9
  14   15
20070714 19520915
      0 10000⊤dual {⎕←⍵} 20070714 19520915                    ⍝ split ccyy mmdd instead of ccyy mm dd
2007 1952
 714  915
20070714 19520915
      0 10000⊤dual {1 1⍉⎕←⍵} 20070714 19520915                ⍝ my birthday this year
2007 1952
 714  915
20070915
      0 10000⊤dual {1 1⍉⎕←⍵} 20071014 19520915                ⍝ but perhaps already passed
2007 1952
1014  915
20070915
      0 10000⊤dual {(2↑2⊃>/⍵)+1 1⍉⎕←⍵} 20071014 19520915      ⍝ my next birthday
2007 1952
1014  915
20080915
      nextbirthday←{0 10000⊤dual {(2↑2⊃>/⍵)+1 1⍉⍵} ⍺ ⍵}       ⍝ as a dyadic fn

      20070714 nextbirthday¨19520915 19540705                 ⍝ my and my sister's next birthdays
20070915 20080705
      Jo SJT KEI Jesus←0705 0915 1217 1225                    ⍝ birth years optional
      20070714 nextbirthday¨Jo SJT KEI Jesus
20080705 20070915 20071217 20071225

      YMDToIDN←{DateToIDN 0 100 100∘⊤⍵}                       ⍝ convert ccyymmdd to IDN
      asIDN←{⊃⍺⍺/YMDToIDN¨⍺ ⍵}                                ⍝ perform ⍺⍺ on args as IDNs
      20070915 -asIDN 20070714                                ⍝ days to my next birthday
63
      20070714{⍺ -⍨asIDN ⍺ nextbirthday ⍵}1225                ⍝ days to Christmas
164

      nb←{⍺+⍳⍵-⍺+1}                                           ⍝ whole numbers between args
      wkday←{(7|⍵)∊⍳5}                                        ⍝ is arg a weekday?

      20070714{+/wkday ⍺ nb asIDN ⍺ nextbirthday ⍵}Jesus      ⍝ count the weekdays to Christmas
116