home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnusmalltalk / date.st < prev    next >
Text File  |  1992-02-15  |  8KB  |  322 lines

  1. "======================================================================
  2. |
  3. |   Date Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbb         12 Jul 91      Added methods for comparing, and for hashing dates.
  34. |              Also fixed storing to use cascaded messages.
  35. |
  36. | sbb         16 Mar 91      Class creation now separate statement.
  37. |
  38. | sbb         22 Sep 90      Changed to reflect the changes required by String
  39. |              printOn:.
  40. |
  41. | sbyrne     25 Apr 89      created.
  42. |
  43. "
  44.  
  45. Magnitude subclass: #Date
  46.       instanceVariableNames: 'days'
  47.       classVariableNames: ''
  48.       poolDictionaries: ''
  49.       category: nil
  50. !
  51.  
  52. Date comment: 
  53. 'My instances represent dates.  My base date is defined to be Jan 1, 1901.
  54. I provide methods for instance creation (including via "symbolic" dates, 
  55. such as "Date newDay: 14 month: #Feb year: 1990"' !
  56.  
  57. Smalltalk at: #DayNameDict put: Dictionary new!
  58. Smalltalk at: #MonthNameDict put: Dictionary new!
  59.  
  60. !Date class methodsFor: 'basic'!
  61.  
  62. initialize
  63.     self initDayNameDict.
  64.     self initMonthNameDict
  65. !
  66.  
  67. initDayNameDict
  68.     | dayNames |
  69.     dayNames _ #(
  70.                  (monday mon)    "1"
  71.                  (tuesday tue)    "2"
  72.                  (wednesday wed) "3"
  73.                  (thursday thu) "4"
  74.                  (friday fri)    "5"
  75.                  (saturday sat) "6"
  76.                  (sunday sun)    "7"
  77.                 ).
  78.     1 to: dayNames size do:
  79.         [ :dayIndex | (dayNames at: dayIndex) do:
  80.         [ :name | DayNameDict at: name put: dayIndex ] ].
  81. !
  82.  
  83. initMonthNameDict
  84.     | monthNames |
  85.     monthNames _ #(
  86.                  (january   jan)    "1"
  87.                  (february  feb)    "2"
  88.                  (march        mar)        "3"
  89.                  (april        apr)        "4"
  90.                  (may)                    "5"
  91.                  (june        jun)        "6"
  92.                  (july        jul)    "7"
  93.                  (august    aug)    "8"
  94.                  (september sep)    "9"
  95.                  (october   oct)    "10"
  96.                  (november  nov)    "11"
  97.                  (december  dec)    "12"
  98.                 ).
  99.     1 to: monthNames size do:
  100.         [ :monthIndex | (monthNames at: monthIndex) do:
  101.         [ :name | MonthNameDict at: name put: monthIndex ] ].
  102. !
  103.  
  104.  
  105. dayOfWeek: dayName
  106.     ^DayNameDict at: dayName asLowercase asSymbol
  107. !
  108.  
  109. nameOfDay: dayIndex
  110.     ^#(Monday Tuesday Wednesday Thursday Friday Saturday Sunday) at: dayIndex
  111. !
  112.  
  113. indexOfMonth: monthName
  114.     ^MonthNameDict at: monthName asLowercase asSymbol
  115. !
  116.  
  117. nameOfMonth: monthIndex
  118.     ^#(January February  March
  119.        April   May       June
  120.        July    August    September
  121.        October November  December) at: monthIndex
  122. !
  123.  
  124. daysInMonth: monthName forYear: yearInteger
  125.     | monthIndex |
  126.     monthIndex _ self indexOfMonth: monthName.
  127.     ^self daysInMonthIndex: monthIndex forYear: yearInteger
  128. !
  129.  
  130. daysInYear: yearInteger
  131.     ^365 + (self leapYear: yearInteger)
  132. !
  133.  
  134. leapYear: yearInteger
  135.     (yearInteger \\ 4 = 0
  136.         and: [ yearInteger \\ 100 ~= 0
  137.         or: [ yearInteger \\ 400 = 0 ] ]) 
  138.         ifTrue: [ ^1 ]
  139.     ifFalse: [ ^0 ]
  140. !
  141.  
  142. dateAndTimeNow
  143.     ^Array with: (Date today) with: (Time now)
  144. !!
  145.  
  146.  
  147.  
  148. !Date class methodsFor: 'instance creation'!
  149.  
  150. today
  151.     | now date |
  152.     now _ Time secondClock.
  153.     date _ now // (24 * 60 * 60).
  154.     ^self new setDays: date  + 25202 "(69 * 365 + 17)"
  155. !
  156.  
  157. fromDays: dayCount
  158.     ^self new setDays: dayCount
  159. !
  160.  
  161. newDay: dayCount year: yearInteger
  162.     ^self new setDays: (dayCount + self yearAsDays: yearInteger)
  163. !
  164.  
  165. newDay: day month: monthName year: yearInteger
  166.     ^self new setDays:
  167.         (day + (self daysUntilMonth: monthName year: yearInteger)
  168.              + (self yearAsDays: yearInteger))
  169. !!
  170.  
  171.  
  172.  
  173. !Date class methodsFor: 'private methods'!
  174.  
  175. yearAsDays: yearInteger
  176.     "Returns the number of days since Jan 1, 1901."
  177.     yearInteger _ yearInteger - 1900.
  178.     ^(yearInteger - 1) * 365
  179.         + (yearInteger // 4)
  180.     - (yearInteger // 100)
  181.     + (yearInteger // 400)
  182. !
  183.  
  184. daysUntilMonth: monthName year: yearInteger
  185.     | monthIndex totalDays |
  186.     totalDays _ 0.
  187.     monthIndex _ self indexOfMonth: monthName.
  188.     1 to: monthIndex - 1 do:
  189.         [ :index | totalDays _ totalDays + (self daysInMonthIndex: index
  190.                                              forYear: yearInteger) ].
  191.     ^totalDays
  192. !
  193.  
  194.  
  195. daysInMonthIndex: monthIndex forYear: yearInteger
  196.     | days |
  197.     days _ #(31 28 31        "Jan Feb Mar"
  198.             30 31 30        "Apr May Jun"
  199.         31 31 30        "Jul Aug Sep"
  200.         31 30 31        "Oct Nov Dec"
  201.         ) at: monthIndex.
  202.     monthIndex = 2
  203.         ifTrue: [ ^days + (self leapYear: yearInteger) ]
  204.     ifFalse: [ ^days ]
  205.  
  206. !!
  207.  
  208.  
  209. !Date methodsFor: 'basic'!
  210.  
  211. addDays: dayCount
  212.     days _ days + dayCount
  213. !
  214.  
  215. subtractDays: dayCount
  216.     days _ days - dayCount
  217. !
  218.  
  219. subtractDate: aDate
  220.     ^days - aDate days
  221. !!
  222.  
  223.  
  224.  
  225. !Date methodsFor: 'comparing'!
  226.  
  227. = aDate
  228.     ^days = aDate days
  229. !
  230.  
  231. < aDate
  232.     ^days < aDate days
  233. !
  234.  
  235. > aDate
  236.     ^days > aDate days
  237. !
  238.     
  239. <= aDate
  240.     ^days <= aDate days
  241. !
  242.  
  243. >= aDate
  244.     ^days >= aDate days
  245. !
  246.  
  247. hash
  248.     ^days
  249. !!
  250.  
  251.  
  252.  
  253. !Date methodsFor: 'printing'!
  254.  
  255. printOn: aStream
  256.     self computeDateParts:
  257.         [ :year :month :day |
  258.         day printOn: aStream.
  259.            aStream nextPut: $-;
  260.             nextPutAll: ((Date nameOfMonth: month) copyFrom: 1 to: 3);
  261.             nextPut: $-.
  262.         year \\ 100 printOn: aStream ]
  263. !!
  264.  
  265.  
  266.  
  267. !Date methodsFor: 'storing'!
  268.  
  269. storeOn: aStream
  270.     "Won't work past around 1200 years in the future"
  271.     aStream nextPut: $(.
  272.     aStream nextPutAll: self classNameString.
  273.     self computeDateParts:
  274.         [ :year :month :day |
  275.         aStream nextPutAll: ' newDay: ';
  276.         store: day;
  277.         nextPutAll: ' month: ';
  278.         store: (Date nameOfMonth: month);
  279.         nextPutAll: ' year: ';
  280.         store: year ].
  281.     aStream nextPut: $)
  282. !!
  283.  
  284.  
  285.  
  286. !Date methodsFor: 'private methods'!
  287.  
  288. days
  289.     ^days
  290. !
  291.  
  292. setDays: dayCount
  293.     days _ dayCount
  294. !
  295.  
  296. computeDateParts: aBlock
  297.     | yearInteger tempDays monthIndex daysInMonth |
  298.     tempDays _ days - (days // 1460) "4*365"
  299.                     + (days // 36500) "100*365"
  300.             - (days // 146000). "400*365"
  301.     yearInteger _ tempDays // 365.
  302.     "The +1 below makes tempDays be 1 based, instead of 0 based, so that the
  303.      first day is 1 Jan 1901 instead of 0 jan 1901"
  304.     tempDays _ days - (yearInteger * 365)
  305.             - (yearInteger // 4)
  306.             + (yearInteger // 100)
  307.             - (yearInteger // 400)
  308.             + 1.
  309.     yearInteger _ yearInteger + 1901.
  310.     monthIndex _ 1.
  311.     [ monthIndex < 12
  312.         and: [ daysInMonth _ Date daysInMonthIndex: monthIndex
  313.                               forYear: yearInteger.
  314.                tempDays > daysInMonth ] ] whileTrue:
  315.         [ monthIndex _ monthIndex + 1.
  316.       tempDays _ tempDays - daysInMonth ].
  317.     ^aBlock value: yearInteger value: monthIndex value: tempDays
  318. !!
  319.  
  320.