Differences between revisions 1 and 2
Revision 1 as of 2007-07-14 10:45:55
Size: 2876
Comment:
Revision 2 as of 2008-02-26 13:36:02
Size: 7597
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
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 ==

 * '''Character vectors''', such as `15/09/1952 06:30:00`, have the advantage of being human readable. This is a solid merit when you are developing with an interpreter and can stop and examine things. This is a useful way to store dates in text files but, given what RDBM systems and XML parsers can do, it is too restrictive for databases or XML documents.

 * '''Numeric vectors''': 6- or 7-element numeric vectors that follow the format of the system clock ⎕TS. They are readable, but not convenient for the more common calculations with dates. But where you want access to the parts (years, months and so on) of dates, they can be just what you need. While numeric timestamps might be an awkward format in other languages, Dyalog’s APL roots make them easy to handle.

 * '''Numeric scalars''', such as `19520915`, are readable and support comparison functions such as `= ≠ > < ≤ ≥ ⍒ ⍋ ⌈ ⌊`. By using floating-point numbers you can include time of day as well, though you sacrifice some readability. For example, 6.30am on that date would be `19520915.063000`. However, you cannot use the important subtract function on dates, though you often want it.

 * '''OA dates and IDNs''' number the days since an chosen start date. IDNs start from 1 Jan 1900; OA dates (a Microsoft standard used in Office applications) from 31 Dec 1899. These subject your dates to subtraction, but at the cost of readability. As with simple numbers, above, times can be included by using real numbers, and as easily razored off (mnemonic) with the ''modulus'' function `|`.

 * '''Day numbers''' number the days of the week: 0 through 7. With IDNs, 0s are Sundays; with OA dates, Saturdays.



----

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

  • Character vectors, such as 15/09/1952 06:30:00, have the advantage of being human readable. This is a solid merit when you are developing with an interpreter and can stop and examine things. This is a useful way to store dates in text files but, given what RDBM systems and XML parsers can do, it is too restrictive for databases or XML documents.

  • Numeric vectors: 6- or 7-element numeric vectors that follow the format of the system clock ⎕TS. They are readable, but not convenient for the more common calculations with dates. But where you want access to the parts (years, months and so on) of dates, they can be just what you need. While numeric timestamps might be an awkward format in other languages, Dyalog’s APL roots make them easy to handle.

  • Numeric scalars, such as 19520915, are readable and support comparison functions such as = ≠ > < ≤ ≥ ⍒ ⍋ ⌈ ⌊. By using floating-point numbers you can include time of day as well, though you sacrifice some readability. For example, 6.30am on that date would be 19520915.063000. However, you cannot use the important subtract function on dates, though you often want it.

  • OA dates and IDNs number the days since an chosen start date. IDNs start from 1 Jan 1900; OA dates (a Microsoft standard used in Office applications) from 31 Dec 1899. These subject your dates to subtraction, but at the cost of readability. As with simple numbers, above, times can be included by using real numbers, and as easily razored off (mnemonic) with the modulus function |.

  • Day numbers number the days of the week: 0 through 7. With IDNs, 0s are Sundays; with OA dates, Saturdays.


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

Studio/EncodeDecodeDates (last edited 2015-04-05 01:47:49 by PierreGilbert)