Date.st
branchjv
changeset 17728 bbc5fa73dfab
parent 17711 39faaaf888b4
child 17732 a1892eeca6c0
--- a/Date.st	Sun Aug 16 18:14:23 2009 +0100
+++ b/Date.st	Wed Aug 19 17:14:36 2009 +0100
@@ -450,7 +450,7 @@
     "Modified: 8.10.1996 / 19:25:39 / cg"
 !
 
-readFrom:aStringOrStream printFormat:aSqueakFormatArrayOrFormatString onError:exceptionBlock
+readFrom:aStringOrStream printFormat:aSqueakFormatArrayOrFormatString language:languageOrNil onError:exceptionBlock
     "return a new Date, reading a printed representation from aStream.
      aSqueakFormatArrayOrFormatString may either be a squeak formatArray
          1   day position (1, 2 or 3)
@@ -461,7 +461,7 @@
      TODO: make this a general feature of all DateAndTime classes.
     "
 
-    |str day month year|
+    |str day month year somePartAssoc|
 
     str := aStringOrStream readStream.
 
@@ -488,19 +488,30 @@
                 |formatStream fc c sel|
 
                 formatStream := aSqueakFormatArrayOrFormatString readStream.
+                
                 [formatStream atEnd] whileFalse:[
                     fc := formatStream next.
                     fc == $% ifTrue:[
                         sel := ''.
-                        [(fc := formatStream peek) notNil and:[ fc isLetter]] whileTrue:[ sel := sel , (formatStream next) ].
-                        (sel asLowercase = 'd') ifTrue:[
-                            day := Integer readFrom:str
+                        (fc := formatStream peek) notNil ifTrue:[
+                            fc = $( ifTrue:[
+                                formatStream next.
+                                sel := formatStream upTo:$)
+                            ] ifFalse:[
+                                sel := sel , (formatStream throughAnyForWhich:[:ch | ch isLetter])
+                            ]
+                        ].
+                        somePartAssoc := self readDatePartFrom:str format:sel language:nil.
+                        somePartAssoc key == #day ifTrue:[
+                            day := somePartAssoc value.
                         ] ifFalse:[
-                            (sel asLowercase = 'm') ifTrue:[
-                                month := Integer readFrom:str
+                            somePartAssoc key == #month ifTrue:[
+                                month := somePartAssoc value.
                             ] ifFalse:[
-                                (sel asLowercase = 'y') ifTrue:[
-                                    year := Integer readFrom:str
+                                somePartAssoc key == #year ifTrue:[
+                                    year := somePartAssoc value.
+                                ] ifFalse:[
+                                    self error:'oops'
                                 ]
                             ]
                         ]
@@ -555,6 +566,51 @@
     "Modified: 8.10.1996 / 19:25:39 / cg"
 !
 
+readFrom:aStringOrStream printFormat:aSqueakFormatArrayOrFormatString onError:exceptionBlock
+    "return a new Date, reading a printed representation from aStream.
+     aSqueakFormatArrayOrFormatString may either be a squeak formatArray
+         1   day position (1, 2 or 3)
+         2   month position (1..3)
+         3   year position (1..3)
+     or a formatString (see printing instance protocol).
+     All of the %-formats as in the printString are supported here.
+     (i.e. %d, %m and %y, %shortMonthName and %monthName)
+     TODO: make this a general feature of all DateAndTime classes.
+    "
+
+    ^ self
+        readFrom:aStringOrStream 
+        printFormat:aSqueakFormatArrayOrFormatString 
+        language:nil 
+        onError:exceptionBlock
+
+    "
+     Date readFrom:'31 December 1992' printFormat:#(1 2 3) onError:'fail' 
+     Date readFrom:'19:11:1999' printFormat:#(1 2 3) onError:'fail'  
+     Date readFrom:'December, 5 1992' printFormat:#(1 2 3) onError:'fail' 
+     Date readFrom:'3-jan-95' printFormat:#(1 2 3) onError:'fail'          
+     Date readFrom:'12/31/1992' printFormat:#(1 2 3) onError:'fail'       
+     Date readFrom:'15.4.1992' printFormat:#(1 2 3) onError:'wrong date'  -> german
+     Date readFrom:'10.4.1992' printFormat:#(1 2 3) onError:'fail'        -> german
+     Date readFrom:'10.4.1992' printFormat:#(1 2 3) onError:['wrong date']
+     Date readFrom:'32.4.1992' printFormat:#(1 2 3) onError:['wrong date']
+     Date readFrom:'fooBar' printFormat:#(1 2 3) onError:['wrong date']
+     Date readFrom:'10.4' printFormat:#(1 2 3) onError:['wrong date']
+     Date readFrom:'10041999' printFormat:#(1 2 3) onError:['wrong date']  
+
+     Date readFrom:'31/12/92' printFormat:#(1 2 3) onError:'fail'       
+     Date readFrom:'31/12/01' printFormat:#(1 2 3) onError:'fail'       
+
+     Date readFrom:'31/12/01' printFormat:'%d %m %y' onError:'fail'       
+     Date readFrom:'12/01' printFormat:'%m %y' onError:'fail'       
+     Date readFrom:'01' printFormat:'%y' onError:'fail'       
+     Date readFrom:'30.01' printFormat:'%d %m' onError:'fail'       
+    "
+
+    "Created: 16.11.1995 / 22:50:17 / cg"
+    "Modified: 8.10.1996 / 19:25:39 / cg"
+!
+
 today
     "return a date, representing today.
      See also: Time now / Timestamp now."
@@ -614,6 +670,16 @@
 
 !Date class methodsFor:'Compatibility-Squeak'!
 
+current
+    "return the current date"
+
+    ^ self today
+
+    "
+     Date current
+    "
+!
+
 fromSeconds:seconds
     "Answer an instance of me which is 'seconds' seconds after January 1, 1901."
 
@@ -1261,6 +1327,25 @@
 
 !Date class methodsFor:'private'!
 
+abbreviatedMonthNamesForLanguage:language
+    |langMonthAbbrevs|
+
+    (MonthAbbrevs isNil or:[EnvironmentChange]) ifTrue:[
+        self initNames
+    ].
+    langMonthAbbrevs := MonthAbbrevs at:(language ? Smalltalk language) ifAbsent:nil.
+    langMonthAbbrevs isNil ifTrue:[
+        langMonthAbbrevs := MonthAbbrevs at:#en.
+    ].
+    ^ langMonthAbbrevs
+
+    "
+     self abbreviatedMonthNamesForLanguage:#en
+     self abbreviatedMonthNamesForLanguage:#de
+     self abbreviatedMonthNamesForLanguage:#es
+    "
+!
+
 dayAbbrevsForLanguage:language
     |langDayAbbrevs|
 
@@ -1355,16 +1440,10 @@
 !
 
 monthAbbrevsForLanguage:language
-    |langMonthAbbrevs|
-
-    (MonthAbbrevs isNil or:[EnvironmentChange]) ifTrue:[
-        self initNames
-    ].
-    langMonthAbbrevs := MonthAbbrevs at:(language ? Smalltalk language) ifAbsent:nil.
-    langMonthAbbrevs isNil ifTrue:[
-        langMonthAbbrevs := MonthAbbrevs at:#en.
-    ].
-    ^ langMonthAbbrevs
+    <resource: #obsolete>
+    "obsolete"
+
+    ^ self abbreviatedMonthNamesForLanguage:language
 !
 
 monthNamesForLanguage:language
@@ -1380,13 +1459,61 @@
     ^ langMonthNames
 ! !
 
-!Date class methodsFor:'private-encoding'!
+!Date class methodsFor:'private-encoding/decoding'!
 
 encodeYear:y month:m day:d
     "the internal encoding is strictly private, 
      and should not be used outside."
 
     ^ (((y * 100) + m) * 100) + d
+!
+
+readDatePartFrom:str format:fmt language:languageOrNil
+    "read a single component (such as %shortName) from str"
+
+    |dayName monthName day month year|
+
+    ((fmt sameAs:'dayName') or:[fmt sameAs:'shortDayName']) ifTrue:[
+        "/ skipped, in case the format is 'monday, 23rd of may...' - not used for decoding
+        dayName := str nextWord.
+        ^ nil.
+    ].
+
+    (fmt sameAs:'d') ifTrue:[
+        day := Integer readFrom:str.
+        ^ #day -> day
+    ].
+    (fmt sameAs:'m') ifTrue:[
+        month := Integer readFrom:str.
+        ^ #month -> month
+    ].
+    fmt = 'y' ifTrue:[
+        year := Integer readFrom:str.
+        year < 100 ifTrue:[
+            ^ #year -> (year + 2000)
+        ].
+        ^ #year -> year
+    ].
+    fmt = 'Y' ifTrue:[
+        year := Integer readFrom:str.
+        year >= 100 ifTrue:[
+            ^ #year -> year
+        ].
+        ^ #year -> (year + 2000) 
+    ].
+    (fmt sameAs:'monthName') ifTrue:[
+        monthName := str nextWord.
+        month := (Date monthNamesForLanguage:languageOrNil) findFirst:[:m | monthName sameAs:m].
+        month == 0 ifTrue:[self error:'invalid month name'].
+        ^ #month -> month
+    ].
+    (fmt sameAs:'shortMonthName') ifTrue:[
+        monthName := str nextWord.
+        month := (Date abbreviatedMonthNamesForLanguage:languageOrNil) findFirst:[:m | monthName sameAs:m].
+        month == 0 ifTrue:[self error:'invalid month name'].
+        ^ #month -> month
+    ].
+    self error:'unknown format specifier'
 ! !
 
 !Date class methodsFor:'private-instance creation'!
@@ -2808,7 +2935,7 @@
 !Date class methodsFor:'documentation'!
 
 version
-    ^ '$Id: Date.st 10448 2009-06-14 16:10:51Z vranyj1 $'
+    ^ '$Id: Date.st 10467 2009-08-19 16:14:36Z vranyj1 $'
 ! !
 
 Date initialize!