13.20 Timedate Interface

ORIGIN '~beta/basiclib/betaenv';
BODY 'private/timedatebody';

(* This library defines a 'time' (and thereby a date) and a 'period'
 * concept.
 * 
 * The library defines numerous operations on time and period values,
 * and time objects, including operations for comparisons, addition,
 * subtractions, printing and reading times and periods.
 * 
 * Given a time, you can ask for the year, day, etc. components of
 * that time, giving the date-related informations of a time.
 *)

--- lib:attributes ---
time:
  (# <<SLOT timeLib:attributes>>;
     
     (* Get and set the individual attributes of the time.
      * 
      * These are normalised, so that you can overflow attributes into
      * each other.  If you e.g. add 23 hours to a time representing
      * 7 o'clock one day, it becomes 6 o'clock the next day!  If you
      * subtract a day from the 1st of a month, you get the last day
      * of the previous month, and so on.
      *)
     
     year: (* set/get the year-component of this(time) *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     month: (* set/get the month-component of this(time). Range: [1-12] *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     day: (* set/get the day-component of this(time). Range: [1-31] *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     hour: (* set/get the hour-component of this(time) *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     minute: (* set/get the minute-component of this(time) *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     sec: (* set/get the sec-component of this(time) *)
       (#
       enter (# value: @integer enter value ... #)
       exit (# value: @integer ... exit value #)
       #);
     weekday:
       (* Returns the weekday of this(time) as an integer.
        *    Monday=1, Tuesday=2, etc.Sunday=7
        *)
       (#
       exit (# value: @integer ... exit value #)
       #);
     dayOfYear: integerValue
       (* returns the day of yeat of this(time) *)
       (# doy: @...
       do doy
       #);
     weekOfYear: integerValue
       (* Returns the number of the week of this(time). Range: [1-53].
        *    previousYear  is invoked if the week is the last week
        *                  of the previous year
        *    followingYear is invoked if the week is the first week
        *                  of the following year
        *)
       (# previousYear:< notification;
          followingYear:< notification;
          woy: @...
       do woy
       #);
     leapYear: booleanValue
       (* Returns true, iff this(time).year is a leap year *)
       (# ly: @...
       do ly
       #);
 
     timePredicate: booleanValue(# other: @time enter other do INNER #);
     
     sameYear:
       (* returns true, iff this(time).year = other.year *)
       timePredicate(# ... #);
     sameMonth:
       (* returns true, if sameYear and this(time).month = other.month *)
       timePredicate(# ... #);
     sameDay:
       (* returns true, if sameMonth and this(time).day = other.day *)
       timePredicate(# ... #);
     sameHour:
       (* returns true, if sameDay and this(time).hour = other.hour *)
       timePredicate(# ... #);
     sameMinute:
       (* returns true, if sameHour and this(time).minute = other.minute *)
       timePredicate(# ... #);
     sameSec:
       (* returns true, if sameMinute and this(time).sec = other.sec *)
       timePredicate(# ... #);
     
     equal:
       (* returns true, iff this(time) = other *)
       sameSec(# #);
     
     before: (* returns true, iff this(time) < other *)
       timePredicate(# ... #);
     after: (* returns true, iff this(time) > other *)
       timePredicate(# ... #);

     between: booleanValue
       (* returns true, iff d1 <= this(time) <= d2 *)
       (# d1,d2: @time
       enter (d1,d2)
       ...
       #);
     
     add: (* moves this(time) forward in time by period 'p' *)
       (# p: @period
       enter p
       ...  
       #);
     
     sub: (* moves this(time) backwards in time by period 'p' *)
       (# p: @period
       enter p
       ...  
       #);
     
     private: @...;

  enter (# year, month, day, hour, minute, sec: @integer;
        enter (year, month, day, hour, minute, sec) 
        ... #)
  exit  (# year, month, day, hour, minute, sec: @integer;
        ...
        exit (year, month, day, hour, minute, sec) 
        #)
  #);

timeNow: (* get the time right now! *)
  (# t: @time;
  ...
  exit t   
  #);

timeNowRef:
  (* as timeNow, except that it returns a time object reference *)
  (# t: ^time
  do &time[]->t[]; timeNow->t;
  exit t[]
  #);

timeMin: (* Mon Nov 24 12:00:00 -4713 *) 
  (# t: @time;
  ... 
  exit t
  #);
                
timeMax: (* in principle infinity *)
  (# t: @time;
  ... 
  exit t
  #);

timeRange: (* the range within which time objects will be normalized *)
  (# exit (timeMin, timeMax) #);

timeDifference:
  (* calculates the time difference (period) between the two times t1 and t2 *)
  (# t1, t2: @time; d: @period
  enter (t1,t2)
  ...  
  exit d
  #);

period:
  (* Periods are used to represent a period of time.
   * 
   * Periods are measured in days, hours, minutes and seconds, and is
   * as such independent of months and years, since these measurements
   * are not time invariant (the length of a year varies, and the same
   * applies for months (28, 29, 30 or 31 days).
   * 
   * Periods can be used to represent the time difference between two
   * times, e.g. between Nov 28 22:45:15 1996 and Dec 3 23:15:30,
   * which is 05#00:30:15.
   * 
   * Periods are also used to represent a duration, e.g. the duration
   * of a standard lecture, 00#00:45:00.
   * 
   * You can add and subtract periods using pAdd and pSub
   * (e.g. '((0,01,30,00),p1)->pAdd->p2' adds one hour and 30 minutes
   * to the period 'p1' and returns the result in 'p2').
   * 
   * And you can measure the time difference between two times 't1'
   * and 't2' by '(t1,t2)->timeDifference->p'.  Finally, you can move
   * a time 't' forward or backwards in time by a given period 'p' by
   * 'p->t.add' and' p->t.sub'.
   *)
  (# <<SLOT periodLib: attributes>>;
     days, hours, minutes, seconds: @integer; 
  enter (days, hours, minutes, seconds)
  exit (days, hours, minutes, seconds)
  #);

pAdd: (* adds two periods and returns the result *)
  (# p1, p2, p3: @period
  enter (p1, p2)
  do p1.days+p2.days->p3.days;
     p1.hours+p2.hours->p3.hours;
     p1.minutes+p2.minutes->p3.minutes;
     p1.seconds+p2.seconds->p3.seconds;
  exit p3
  #);

pSub: (* subtracts two periods and returns the result *)
  (# p1, p2, p3: @period
  enter (p1, p2)
  do p1.days-p2.days->p3.days;
     p1.hours-p2.hours->p3.hours;
     p1.minutes-p2.minutes->p3.minutes;
     p1.seconds-p2.seconds->p3.seconds;
  exit p3
  #);

(* Input/Output utilities:
 *
 * Formats:
 *    Time:   Www Mmm Dd Yyyy Hh:Mm:Ss
 *    Date:   Www Mmm Dd Yyyy
 *    Clock:  Hh:Mm:Ss
 *    Period: Dd#Hh:Mm:Ss
 * 
 * where Www  is the weekday (Mon, Tue, etc.)
 *       Mmm  is the month (Jan, Feb, etc.)
 *       Dd   is the date
 *       Hh   is hours
 *       Mm   is minutes
 *       Ss   is seconds
 *       Yyyy is the year
 *)

putTime: (* prints a time value on screen *)
  screen.putTime(# do INNER #);
getTime: (* reads a time value from the keyboard *)
  keyboard.getTime(# do INNER #);

putDate: (* prints the date portion of a time value on screen *)
  screen.putDate(# do INNER #);
getDate:
  (* reads a date value from the keyboard.  The clock part of the
   * time value will be 00:00:00
   *)
  keyboard.getDate(# do INNER #);

putClock: (* prints the clock portion of a time value on screen *)
  screen.putClock(# do INNER #);
getClock:
  (* reads a clock value from the keyboard.  The date part of the
   * time value will be Jan 01, 0000.
   *)
  keyboard.getClock(# do INNER #);

putPeriod: (* prints a period value on screen *)
  screen.putPeriod(# #);
getPeriod: (* reads a period value from the keyboard *)
  keyboard.getPeriod(# #);

--- streamLib:attributes ---

putTime:  (* prints a time value on this(stream) *)
  (# t: @time;
  enter t
  ...
  #);
getTime: (* reads a time value from this(stream) *)
  (# t: @time;
  ...
  exit t
  #);

putDate: (* prints the date portion of a time value on screen *)
  (# t: @time;
  enter t
  ...
  #);
getDate:
  (* reads a date value from the keyboard.  The clock part of the
   * time value will be 00:00:00
   *)
  (# t: @time;
  ...
  exit t
  #);

putClock: (* prints the clock portion of a time value on screen *)
  (# t: @time;
  enter t
  ...
  #);
getClock:
  (* reads a clock value from the keyboard.  The date part
   * of the time value will be Jan 01, 0000
   *)
  (# t: @time;
  ...
  exit t
  #);

putPeriod: (* prints a period value on this(stream) *)
  (# p: @period
  enter p
  ...
  #);
getPeriod: (* prints a period value on this(stream) *)
  (# p: @period
  ...
  exit p
  #)


13.20 Timedate Interface
© 1990-2004 Mjølner Informatics
[Modified: Thursday June 29th 2000 at 0:44]