home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / progs / daystil.icn < prev    next >
Text File  |  2000-07-29  |  6KB  |  231 lines

  1. ############################################################################
  2. #
  3. #    File:     daystil.icn
  4. #
  5. #    Subject:  Program to calculate the number of days until a given date
  6. #
  7. #    Author:   Nevin Liber
  8. #
  9. #    Date:     June 29, 1994
  10. #
  11. ###########################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #
  17. #   Usage:    daystil sMonth iDay
  18. #
  19. #   Returns:
  20. #       0   number of days written on &output
  21. #       1   Usage message on &errout (bad parameters)
  22. #
  23. #   Revision History:
  24. #       <1> njl  6/29/94 9:50 PM        First written
  25. #
  26. #   This program calculates the number of days between the current date
  27. #   and the date specified on the command line, and writes this number to
  28. #   &output.  This is useful if you want to know how many days it is
  29. #   until a birthday, wedding day, etc.
  30. #
  31. #   The date on the command line can be specified in a variety of ways.
  32. #   For instance, if you wanted to know how many days it is until
  33. #   August 12 (my birthday), you could specify it as "August 12", "Aug 12",
  34. #   "12 August", or "12 aUGuS", among others.  The match is case
  35. #   insensitive, and the arguments will be accepted as long as exactly
  36. #   one of them is an integer, and if there are exactly two arguments.
  37. #
  38. ###########################################################################
  39. #
  40. #   NumberOfDays(sMonth, iDay, iYear) : iNumberOfDays
  41. #
  42. #   NumberOfDays() returns the number of days into iYear that sMonth/iDay
  43. #   occurs.  For instance, NumberOfDays("February", 28) returns 59, since
  44. #   it is the 59th day into any year.  Leap years from 1901 until 2099
  45. #   are taken into account.  It fails if any parameters are bad.
  46. #
  47. #   Defaults:
  48. #       sMonth  current month
  49. #       iDay    current day of the current month
  50. #       iYear   current year
  51. #
  52. ############################################################################
  53.  
  54. procedure NumberOfDays(sMonth, iDay, iYear)
  55.  
  56.     static    LMonths
  57.     static    LDays
  58.     static    sThisMonth
  59.     static    iThisDay
  60.     static    iThisYear
  61.     local    iDays
  62.     local    i
  63.  
  64.     initial {    
  65.         LMonths := [
  66.             "january",
  67.             "february",
  68.             "march",
  69.             "april",
  70.             "may",
  71.             "june",
  72.             "july",
  73.             "august",
  74.             "september",
  75.             "october",
  76.             "november",
  77.             "december"
  78.         ]
  79.  
  80.         LDays := [
  81.             31,
  82.             28,
  83.             31,
  84.             30,
  85.             31,
  86.             30,
  87.             31,
  88.             31,
  89.             30,
  90.             31,
  91.             30
  92.         ]
  93.  
  94.         &dateline ? {
  95.             &pos := find(" ") + 1
  96.             sThisMonth := tab(find(" "))
  97.             &pos +:= 1
  98.             iThisDay := integer(tab(find(",")))
  99.             &pos +:= 2
  100.             iThisYear := integer(move(4))
  101.         }
  102.     }
  103.  
  104.     /sMonth := sThisMonth
  105.     /iDay := iThisDay
  106.     /iYear := iThisYear
  107.  
  108.     sMonth := string(sMonth) | fail
  109.     iDay := integer(iDay) | fail
  110.     iYear := integer(iYear) | fail
  111.  
  112.     if 0 ~= iYear % 4 then {
  113.         LDays[2] := 28
  114.     } else {
  115.         LDays[2] := 29
  116.     }
  117.  
  118.     iDays := iDay
  119.     every i := 1 to *LMonths do {
  120.         if CaselessMatch(sMonth, LMonths[i]) then {
  121.             return iDays
  122.         }
  123.         iDays +:= LDays[i]
  124.     }
  125.  
  126. end
  127.  
  128.  
  129. ############################################################################
  130. #
  131. #   CaselessMatch(s1, s2, i1, i2) : i3  caseless match of initial string
  132. #
  133. #    CaselessMatch(s1, s2, i1, i2) produces i1 + *s1 if
  134. #   map(s1) == map(s2[i1+:*s1]) but fails otherwise.
  135. #
  136. #   This is the same as the built-in function match(), except the
  137. #   comparisons are done without regard to case.
  138. #
  139. #   Defaults:
  140. #       s2      &subject
  141. #       i1      &pos if s2 is defaulted, otherwise 1
  142. #       i2      0
  143. #
  144. #   Errors:
  145. #       101     i1 or i2 not integer
  146. #       103     s1 or s2 not string
  147. #
  148. ############################################################################
  149.  
  150. procedure CaselessMatch(s1, s2, i1, i2)
  151.  
  152.     s1 := map(string(s1))
  153.     /i1 := (/s2 & &pos)
  154.     s2 := map(string(s2) | (/s2 & &subject))
  155.  
  156.     return match(s1, s2, i1, i2)
  157.     
  158.  
  159. end
  160.  
  161.  
  162. ############################################################################
  163. #
  164. #   Usage(fErrout, iStatus)     write usage message to fErrout and exit
  165. #
  166. #   Usage(fErrout, iStatus) writes the usage message to file fErrout
  167. #   and exits with exit status code iStatus
  168. #
  169. #   Defaults:
  170. #       fErrout  &errout
  171. #       iStatus  1
  172. #
  173. ############################################################################
  174.  
  175. procedure Usage(fErrout, iStatus)
  176.  
  177.     /fErrout := &errout
  178.     iStatus := (integer(iStatus) | 1)
  179.  
  180.     write(fErrout, "Usage: DaysTil sMonth iDay")
  181.     exit(iStatus)
  182.  
  183. end
  184.  
  185.  
  186. ############################################################################
  187. #
  188. #   main(LArguments)
  189. #
  190. #    main(LArguments) checks to make sure there are two arguments, exactly
  191. #   one of which is an integer.  If so, it tries to calculate the number
  192. #   of days between the current date and the date specified, taking into
  193. #   account if the specified date occurs after today's date only in the
  194. #   following year.  On a parameter error, it writes the usage message
  195. #   to &errout and exits with status 1.  Otherwise, it writes the number
  196. #   of days to &output and exits with status 0.
  197. #
  198. ############################################################################
  199.  
  200. procedure main(LArguments)
  201.  
  202.     local    sArgument
  203.     local    sMonth
  204.     local    iDay
  205.     local    iToday
  206.     local    iNumberOfDays
  207.  
  208.  
  209.     if 2 ~= *LArguments then {
  210.         Usage()
  211.     }
  212.  
  213.     every sArgument := !LArguments do {
  214.         (iDay := integer(sArgument)) | (sMonth := sArgument)
  215.     }
  216.  
  217.     if /iDay | /sMonth then {
  218.         Usage()
  219.     }
  220.     
  221.     iToday := NumberOfDays()
  222.     iNumberOfDays := NumberOfDays(sMonth, iDay) | Usage()
  223.     if iNumberOfDays < iToday then {
  224.         iNumberOfDays := NumberOfDays("december", 31) + NumberOfDays(sMonth, iDay, integer(&date[1+:4]) + 1)
  225.     }
  226.     
  227.     write(iNumberOfDays - iToday)
  228.  
  229. end
  230.  
  231.