--- a/AbstractTime.st Sat Jun 06 06:39:31 2015 +0200
+++ b/AbstractTime.st Sun Jun 07 06:38:49 2015 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1995 by Claus Gittinger
All Rights Reserved
@@ -287,6 +289,7 @@
^ '%h:%m:%s'
! !
+
!AbstractTime class methodsFor:'private-instance creation'!
fromOSTime:osTime
@@ -369,6 +372,24 @@
"Modified: 1.7.1996 / 15:20:14 / cg"
! !
+!AbstractTime class methodsFor:'reading'!
+
+readFrom:aStringOrStream format:formatString
+ "see format description in readFrom:format:language:onError:"
+
+ ^ self
+ readFrom:aStringOrStream format:formatString language:nil
+ onError:[
+ self conversionErrorSignal raiseErrorString:'Timestamp format error'
+ ].
+!
+
+readFrom:aStringOrStream format:formatString onError:exceptionalValue
+ "see format description in readFrom:format:language:onError:"
+
+ ^ self readFrom:aStringOrStream format:formatString language:nil onError:exceptionalValue
+! !
+
!AbstractTime class methodsFor:'timing evaluations'!
microsecondsToRun:aBlock
@@ -1439,10 +1460,10 @@
!AbstractTime class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/AbstractTime.st,v 1.91 2015-02-03 19:01:47 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/AbstractTime.st,v 1.92 2015-06-06 12:56:45 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/AbstractTime.st,v 1.91 2015-02-03 19:01:47 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/AbstractTime.st,v 1.92 2015-06-06 12:56:45 cg Exp $'
! !
--- a/Date.st Sat Jun 06 06:39:31 2015 +0200
+++ b/Date.st Sun Jun 07 06:38:49 2015 +0200
@@ -298,7 +298,8 @@
"return a new Date, given the day-number starting with 0 at 1.Jan 0;
(i.e. 'Date fromDaysSince0:0' returns 1st Jan. 0).
Date asDaysSince0 is the reverse operation.
- Notice, that this is a private interface"
+ Notice, that this is a private interface.
+ Also notice: does not care for Gregorian/Julisn calendar change"
|year rest d yearIncrement yearAsDaysFrom0|
@@ -446,16 +447,266 @@
"
!
+readFrom:aStringOrStream format:aSqueakFormatArrayOrFormatString
+ "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)."
+
+ ^ self
+ readFrom:aStringOrStream
+ format:aSqueakFormatArrayOrFormatString
+ onError:[ self conversionErrorSignal raise ]
+
+ "
+ Date readFrom:'19:11:1999' format:#( 1 2 3 )
+ Date readFrom:'19-nov-1999' format:#( 1 2 3 )
+ Date readFrom:'19:11:1999' format:#( 2 1 3 ) -> exception: wrong month
+ Date readFrom:'5:12:1999' format:#( 2 1 3 )
+ Date readFrom:'may-12-1999' format:#( 2 1 3 )
+ Date readFrom:'1999 may 12' format:#( 3 2 1 )
+ Date readFrom:'12/31/2001' format:#( 2 1 3 )
+ Date readFrom:' 31.08.2001' format:#( 1 2 3 )
+ Date readFrom:' 31.dec.2001' format:#( 1 2 3 )
+ Date readFrom:' 31.Dec.2001' format:#( 1 2 3 )
+ Date readFrom:' 31.dez.2001' format:#( 1 2 3 )
+
+ Date readFrom:'31/12/01' format:'%d %m %y' onError:'fail'
+ Date readFrom:'12/01' format:'%m %y' onError:'fail'
+ Date readFrom:'01' format:'%y' onError:'fail'
+ Date readFrom:'30.01' format:'%d %m' onError:'fail'
+ "
+
+ "Created: 16.11.1995 / 22:50:17 / cg"
+ "Modified: 8.10.1996 / 19:25:39 / cg"
+!
+
+readFrom:aStringOrStream format:aFormatStringOrSqueakFormatArray language:languageOrNil onError:exceptionBlock
+ "return a new Date, reading a printed representation from aStream.
+ aFormatStringOrSqueakFormatArray 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).
+ For now %d, %m, %monthName, %shortMonthName, %y, %Y, %y1900, %y2000, %y1950 and %y1980 are supported in the formatString.
+ y1900 converts 2-digit year YY into 19YY,
+ y2000 into 20YY.
+ y1950, y1980 and Y are special;
+ if the year is below 50/80/70, it is converted to 20YY, otherwise to 19YY.
+ The formatString can have any of these characters '-.:,;/' as separator.
+ The format may be preceeded by a single numeric length (as in %2d) to specify how many
+ characters to read.
+ The formatString can also use a space as separator (for ex. '%d %m %y') and any separator will be allowed.
+ However, when a character separator is defined, only that separator will be expected.
+ TODO: make this a general feature of all DateAndTime classes.
+ "
+
+ |str|
+
+ str := aStringOrStream readStream.
+
+ [
+ |day month year dayOfYear monthAndDay|
+
+ aFormatStringOrSqueakFormatArray isArray ifTrue:[
+ |arg|
+
+ arg := Array new:3.
+
+ 1 to:3 do:[:i||v|
+ [str peek isLetterOrDigit] whileFalse:[str next].
+
+ v := (str peek isDigit) ifTrue:[Integer readFrom:str]
+ ifFalse:[str nextAlphaNumericWord].
+ arg at:i put:v
+ ].
+ year := arg at:(aFormatStringOrSqueakFormatArray at:3).
+ day := arg at:(aFormatStringOrSqueakFormatArray at:1).
+ month := arg at:(aFormatStringOrSqueakFormatArray at:2).
+ ] ifFalse:[
+ |formatStream fc c sel somePartAssoc len lStr|
+
+ formatStream := aFormatStringOrSqueakFormatArray readStream.
+
+ [formatStream atEnd] whileFalse:[
+ fc := formatStream next.
+ fc == $% ifTrue:[
+ sel := ''.
+ len := nil.
+ (fc := formatStream peekOrNil) notNil ifTrue:[
+ fc isDigit ifTrue:[
+ len := fc digitValue.
+ formatStream next.
+ ]
+ ].
+
+ (fc := formatStream peekOrNil) notNil ifTrue:[
+ fc == $( ifTrue:[
+ formatStream next.
+ sel := formatStream upTo:$)
+ ] ifFalse:[
+ sel := sel , (formatStream throughAnyForWhich:[:ch | ch isLetter])
+ ]
+ ].
+ len notNil ifTrue:[
+ lStr := str next:len.
+ somePartAssoc := self readDatePartFrom:lStr readStream format:sel language:languageOrNil.
+ ] ifFalse:[
+ somePartAssoc := self readDatePartFrom:str format:sel language:languageOrNil.
+ ].
+ somePartAssoc key == #day ifTrue:[
+ day := somePartAssoc value.
+ ] ifFalse:[somePartAssoc key == #month ifTrue:[
+ month := somePartAssoc value.
+ ] ifFalse:[somePartAssoc key == #year ifTrue:[
+ year := somePartAssoc value.
+ ] ifFalse:[somePartAssoc key == #dayOfYear ifTrue:[
+ dayOfYear := somePartAssoc value.
+ ] ifFalse:[
+ self error:'unexpected date part'
+ ]]]].
+ ] ifFalse:[
+ fc == Character space ifTrue:[
+ "/ Skip most possible separator characters
+ "/ (if not enough, should check for isNationalAlphaNumeric instead)
+ [(c := str peek) isSeparator
+ or:[ '-.:,;/\|?<>[]{}()#@!!$&^+=~*_"`' includes:c]] whileTrue:[str next].
+ ] ifFalse:[
+ str skipSeparators.
+ str next ~= fc ifTrue:[^ exceptionBlock value].
+ str skipSeparators.
+ ]
+ ]
+ ].
+ ].
+
+ dayOfYear notNil ifTrue:[
+ monthAndDay := Date monthAndDayFromDayInYear:dayOfYear forYear:year.
+ month := (monthAndDay at:1).
+ day := (monthAndDay at:2).
+ ].
+
+ day isNil ifTrue:[ day := 1 ].
+ month isNil ifTrue:[ month := 1 ].
+ year isNil ifTrue:[ year := Date today year ].
+
+ (year between:0 and:99) ifTrue:[
+ year := UserPreferences current twoDigitDateHandler value:year.
+ ].
+ ^ self newDay:day month:month year:year.
+ ] on:Error do:[:ex| ^ exceptionBlock value].
+
+ "
+ 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'
+ Date readFrom:'300180' printFormat:'%2d%2m%2y' onError:'fail'
+
+ Date readFrom:'300170' printFormat:'%2d%2m%2y' onError:'fail' - gives 2070 as year
+ Date readFrom:'300170' printFormat:'%2d%2m%2Y' onError:'fail' - gives 1970 as year
+ Date readFrom:'300169' printFormat:'%2d%2m%2y' onError:'fail' - gives 2069 as year
+ Date readFrom:'300169' printFormat:'%2d%2m%2Y' onError:'fail' - gives 2069 as year
+
+ Date readFrom:'300170' printFormat:'%2d%2m%2(y1950)' onError:'fail' - gives 1970 as year
+ Date readFrom:'300170' printFormat:'%2d%2m%2(y1980)' onError:'fail' - gives 2070 as year
+ Date readFrom:'300181' printFormat:'%2d%2m%2(y1980)' onError:'fail' - gives 1981 as year
+
+ Date readFrom:'2015103' printFormat:'%4y%3(dayOfYear)' onError:'fail'
+
+ Date readFrom:'3-3-1995' printFormat:'%d %m %y' language: #de onError:'fail'
+ Date readFrom:'3-März-1995' printFormat:'%d %monthName %y' language: #de onError:'fail'
+ Date readFrom:'3-mär-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3/mär/1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3/mär/1995' printFormat:'%d-%shortMonthName-%y' language: #de onError:'fail'
+ Date readFrom:'3-dez-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3-Dez-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3-Dezember-1995' printFormat:'%d %monthName %y' language: #de onError:'fail'
+
+ "
+
+ "Created: 16.11.1995 / 22:50:17 / cg"
+ "Modified: 8.10.1996 / 19:25:39 / cg"
+!
+
+readFrom:aStringOrStream format: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)
+ In addition, %Y, %y1900, %y2000, %y1950 and %y1980 are supported:
+ y1900 converts 2-digit year YY into 19YY, y2000 into 20YY.
+ y1950, y1980 and Y are special; if the year is below 50/80/70, it is converted to 20YY, otherwise to 19YY.
+ TODO: make this a general feature of all DateAndTime classes.
+ "
+
+ ^ self
+ readFrom:aStringOrStream
+ format:aSqueakFormatArrayOrFormatString
+ language:nil
+ onError:exceptionBlock
+
+ "
+ Date readFrom:'31 December 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'19:11:1999' format:#(1 2 3) onError:'fail'
+ Date readFrom:'December, 5 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'3-jan-95' format:#(1 2 3) onError:'fail'
+ Date readFrom:'12/31/1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'15.4.1992' format:#(1 2 3) onError:'wrong date' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:'fail' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'32.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'fooBar' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10.4' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10041999' format:#(1 2 3) onError:['wrong date']
+
+ Date readFrom:'31/12/92' format:#(1 2 3) onError:'fail'
+ Date readFrom:'31/12/01' format:#(1 2 3) onError:'fail'
+
+ Date readFrom:'31/12/01' format:'%d %m %y' onError:'fail'
+ Date readFrom:'12/01' format:'%m %y' onError:'fail'
+ Date readFrom:'01' format:'%y' onError:'fail'
+ Date readFrom:'30.01' format:'%d %m' onError:'fail'
+ Date readFrom:'311201' format:'%2d%2m%2y' onError:'fail'
+ "
+
+ "Created: 16.11.1995 / 22:50:17 / cg"
+ "Modified: 8.10.1996 / 19:25:39 / cg"
+!
+
readFrom:aStringOrStream onError:exceptionBlock
"return a new Date, reading a printed representation from aStream.
Notice, that this is not the storeString format and
is different from the format expected by readFrom:.
+
BUG:
- This method handles american format (i.e. month/day/year),
- common format with letter month in the middle (10 December 2007)
+ For Smalltalk compatibility, this method handles american format (i.e. month/day/year),
+ the common format with letter month in the middle (10 December 2007)
and ISO format (yyyy-mm-dd) - as long as yyyy is > 12.
- It does not handle the german/french and other dd-mm-yyyy.
+ It does NOT handle the german/french and other dd-mm-yyyy formats.
use readFrom:printFormat:onError: for this."
^ [
@@ -519,212 +770,6 @@
"Modified: 8.10.1996 / 19:25:39 / cg"
!
-readFrom:aStringOrStream printFormat:aSqueakFormatArrayOrFormatString
- "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)."
-
- ^ self
- readFrom:aStringOrStream
- printFormat:aSqueakFormatArrayOrFormatString
- onError:[ self conversionErrorSignal raise ]
-
- "
- Date readFrom:'19:11:1999' printFormat:#( 1 2 3 )
- Date readFrom:'19-nov-1999' printFormat:#( 1 2 3 )
- Date readFrom:'19:11:1999' printFormat:#( 2 1 3 ) -> exception: wrong month
- Date readFrom:'5:12:1999' printFormat:#( 2 1 3 )
- Date readFrom:'may-12-1999' printFormat:#( 2 1 3 )
- Date readFrom:'1999 may 12' printFormat:#( 3 2 1 )
- Date readFrom:'12/31/2001' printFormat:#( 2 1 3 )
- Date readFrom:' 31.08.2001' printFormat:#( 1 2 3 )
- Date readFrom:' 31.dec.2001' printFormat:#( 1 2 3 )
- Date readFrom:' 31.Dec.2001' printFormat:#( 1 2 3 )
- Date readFrom:' 31.dez.2001' printFormat:#( 1 2 3 )
-
- 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"
-!
-
-readFrom:aStringOrStream printFormat:aFormatStringOrSqueakFormatArray language:languageOrNil onError:exceptionBlock
- "return a new Date, reading a printed representation from aStream.
- aFormatStringOrSqueakFormatArray 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).
- For now %d, %m, %monthName, %shortMonthName and %y are supported in the formatString.
- The formatString can have any of these characters '-.:,;/' as separator.
- The formatString can also use a space as separator (for ex. '%d %m %y') and any separator will be allowed.
- However, when a character separator is defined, only that separator will be expected.
- TODO: make this a general feature of all DateAndTime classes.
- "
-
- |str|
-
- str := aStringOrStream readStream.
-
- [
- |day month year|
-
- aFormatStringOrSqueakFormatArray isArray ifTrue:[
- |arg|
-
- arg := Array new:3.
-
- 1 to:3 do:[:i||v|
- [str peek isLetterOrDigit] whileFalse:[str next].
-
- v := (str peek isDigit) ifTrue:[Integer readFrom:str]
- ifFalse:[str nextAlphaNumericWord].
- arg at:i put:v
- ].
- year := arg at:(aFormatStringOrSqueakFormatArray at:3).
- day := arg at:(aFormatStringOrSqueakFormatArray at:1).
- month := arg at:(aFormatStringOrSqueakFormatArray at:2).
- ] ifFalse:[
- |formatStream fc c sel somePartAssoc|
-
- formatStream := aFormatStringOrSqueakFormatArray readStream.
-
- [formatStream atEnd] whileFalse:[
- fc := formatStream next.
- fc == $% ifTrue:[
- sel := ''.
- (fc := formatStream peekOrNil) notNil ifTrue:[
- fc == $( ifTrue:[
- formatStream next.
- sel := formatStream upTo:$)
- ] ifFalse:[
- sel := sel , (formatStream throughAnyForWhich:[:ch | ch isLetter])
- ]
- ].
- somePartAssoc := self readDatePartFrom:str format:sel language:languageOrNil.
- somePartAssoc key == #day ifTrue:[
- day := somePartAssoc value.
- ] ifFalse:[somePartAssoc key == #month ifTrue:[
- month := somePartAssoc value.
- ] ifFalse:[somePartAssoc key == #year ifTrue:[
- year := somePartAssoc value.
- ] ifFalse:[
- self error:'unexpected date part'
- ]]].
- ] ifFalse:[
- fc == Character space ifTrue:[
- "/ Skip most possible separator characters
- "/ (if not enough, should check for isNationalAlphaNumeric instead)
- [(c := str peek) isSeparator
- or:[ '-.:,;/\|?<>[]{}()#@!!$&^+=~*_"`' includes:c]] whileTrue:[str next].
- ] ifFalse:[
- str skipSeparators.
- str next ~= fc ifTrue:[^ exceptionBlock value].
- str skipSeparators.
- ]
- ]
- ].
- ].
-
- day isNil ifTrue:[ day := 1 ].
- month isNil ifTrue:[ month := 1 ].
- year isNil ifTrue:[ year := Date today year ].
-
- (year between:0 and:99) ifTrue:[
- year := UserPreferences current twoDigitDateHandler value:year.
- ].
- ^ self newDay:day month:month year:year.
- ] on:Error do:[:ex| ^ exceptionBlock value].
-
- "
- 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'
-
- Date readFrom:'3-3-1995' printFormat:'%d %m %y' language: #de onError:'fail'
- Date readFrom:'3-März-1995' printFormat:'%d %monthName %y' language: #de onError:'fail'
- Date readFrom:'3-mär-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
- Date readFrom:'3/mär/1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
- Date readFrom:'3/mär/1995' printFormat:'%d-%shortMonthName-%y' language: #de onError:'fail'
- Date readFrom:'3-dez-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
- Date readFrom:'3-Dez-1995' printFormat:'%d %shortMonthName %y' language: #de onError:'fail'
- Date readFrom:'3-Dezember-1995' printFormat:'%d %monthName %y' language: #de onError:'fail'
-
- "
-
- "Created: 16.11.1995 / 22:50:17 / cg"
- "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."
@@ -1698,6 +1743,151 @@
self obsoleteMethodWarning:'use #leapYear: (2014-09)'.
^ self leapYear:yearInteger
+!
+
+readFrom:aStringOrStream printFormat:aSqueakFormatArrayOrFormatString
+ "OBSOLETE: kept for backward compatibility.
+ 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)."
+
+ ^ self
+ readFrom:aStringOrStream
+ format:aSqueakFormatArrayOrFormatString
+
+ "
+ Date readFrom:'19:11:1999' printFormat:#( 1 2 3 )
+ Date readFrom:'19-nov-1999' printFormat:#( 1 2 3 )
+ Date readFrom:'19:11:1999' printFormat:#( 2 1 3 ) -> exception: wrong month
+ Date readFrom:'5:12:1999' printFormat:#( 2 1 3 )
+ Date readFrom:'may-12-1999' printFormat:#( 2 1 3 )
+ Date readFrom:'1999 may 12' printFormat:#( 3 2 1 )
+ Date readFrom:'12/31/2001' printFormat:#( 2 1 3 )
+ Date readFrom:' 31.08.2001' printFormat:#( 1 2 3 )
+ Date readFrom:' 31.dec.2001' printFormat:#( 1 2 3 )
+ Date readFrom:' 31.Dec.2001' printFormat:#( 1 2 3 )
+ Date readFrom:' 31.dez.2001' printFormat:#( 1 2 3 )
+
+ 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"
+!
+
+readFrom:aStringOrStream printFormat:aFormatStringOrSqueakFormatArray language:languageOrNil onError:exceptionBlock
+ "OBSOLETE: kept for backward compatibility
+ return a new Date, reading a printed representation from aStream.
+ aFormatStringOrSqueakFormatArray 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).
+ For now %d, %m, %monthName, %shortMonthName, %y, %y1900, %y2000, %y1950 and %y1980 are supported in the formatString.
+ y1900 converts 2-digit year YY into 19YY, y2000 into 20YY.
+ y1950 and y1980 are special; if the year is below 50/80, it is converted to 20YY, otherwise to 19YY.
+ The formatString can have any of these characters '-.:,;/' as separator.
+ The format may be preceeded by a single numeric length (as in %2d) to specify how many
+ characters to read.
+ The formatString can also use a space as separator (for ex. '%d %m %y') and any separator will be allowed.
+ However, when a character separator is defined, only that separator will be expected.
+ TODO: make this a general feature of all DateAndTime classes.
+ "
+
+ ^ self readFrom:aStringOrStream format:aFormatStringOrSqueakFormatArray language:languageOrNil onError:exceptionBlock
+
+
+ "
+ Date readFrom:'31 December 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'19:11:1999' format:#(1 2 3) onError:'fail'
+ Date readFrom:'December, 5 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'3-jan-95' format:#(1 2 3) onError:'fail'
+ Date readFrom:'12/31/1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'15.4.1992' format:#(1 2 3) onError:'wrong date' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:'fail' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'32.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'fooBar' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10.4' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10041999' format:#(1 2 3) onError:['wrong date']
+
+ Date readFrom:'31/12/92' format:#(1 2 3) onError:'fail'
+ Date readFrom:'31/12/01' format:#(1 2 3) onError:'fail'
+
+ Date readFrom:'31/12/01' format:'%d %m %y' onError:'fail'
+ Date readFrom:'12/01' format:'%m %y' onError:'fail'
+ Date readFrom:'01' format:'%y' onError:'fail'
+ Date readFrom:'30.01' format:'%d %m' onError:'fail'
+ Date readFrom:'300180' format:'%2d%2m%2y' onError:'fail'
+
+ Date readFrom:'300170' format:'%2d%2m%2y' onError:'fail' - gives 2070 as year
+ Date readFrom:'300170' format:'%2d%2m%2(y1950)' onError:'fail' - gives 1970 as year
+ Date readFrom:'300170' format:'%2d%2m%2(y1980)' onError:'fail' - gives 2070 as year
+ Date readFrom:'300181' format:'%2d%2m%2(y1980)' onError:'fail' - gives 1981 as year
+
+ Date readFrom:'3-3-1995' format:'%d %m %y' language: #de onError:'fail'
+ Date readFrom:'3-März-1995' format:'%d %monthName %y' language: #de onError:'fail'
+ Date readFrom:'3-mär-1995' format:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3/mär/1995' format:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3/mär/1995' format:'%d-%shortMonthName-%y' language: #de onError:'fail'
+ Date readFrom:'3-dez-1995' format:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3-Dez-1995' format:'%d %shortMonthName %y' language: #de onError:'fail'
+ Date readFrom:'3-Dezember-1995' format:'%d %monthName %y' language: #de onError:'fail'
+ "
+
+ "Created: 16.11.1995 / 22:50:17 / cg"
+ "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)
+ In addition, %y1900, %y2000, %y1950 and %y1980 are supported:
+ y1900 converts 2-digit year YY into 19YY, y2000 into 20YY.
+ y1950 and y1980 are special; if the year is below 50/80, it is converted to 20YY, otherwise to 19YY.
+ TODO: make this a general feature of all DateAndTime classes.
+ "
+
+ ^ self readFrom:aStringOrStream format:aSqueakFormatArrayOrFormatString onError:exceptionBlock
+
+ "
+ Date readFrom:'31 December 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'19:11:1999' format:#(1 2 3) onError:'fail'
+ Date readFrom:'December, 5 1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'3-jan-95' format:#(1 2 3) onError:'fail'
+ Date readFrom:'12/31/1992' format:#(1 2 3) onError:'fail'
+ Date readFrom:'15.4.1992' format:#(1 2 3) onError:'wrong date' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:'fail' -> german
+ Date readFrom:'10.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'32.4.1992' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'fooBar' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10.4' format:#(1 2 3) onError:['wrong date']
+ Date readFrom:'10041999' format:#(1 2 3) onError:['wrong date']
+
+ Date readFrom:'31/12/92' format:#(1 2 3) onError:'fail'
+ Date readFrom:'31/12/01' format:#(1 2 3) onError:'fail'
+
+ Date readFrom:'31/12/01' format:'%d %m %y' onError:'fail'
+ Date readFrom:'12/01' format:'%m %y' onError:'fail'
+ Date readFrom:'01' format:'%y' onError:'fail'
+ Date readFrom:'30.01' format:'%d %m' onError:'fail'
+ Date readFrom:'311201' format:'%2d%2m%2y' onError:'fail'
+ "
+
+ "Created: 16.11.1995 / 22:50:17 / cg"
+ "Modified: 8.10.1996 / 19:25:39 / cg"
! !
!Date class methodsFor:'private'!
@@ -1805,7 +1995,7 @@
readDatePartFrom:str format:fmt language:languageOrNil
"read a single component (such as %shortName) from str"
- |dayName monthName day month year format string |
+ |dayName monthName day month year format string dayOfYear|
format := fmt.
string := str throughAnyForWhich:[:ch | ch isNationalAlphaNumeric].
@@ -1815,12 +2005,12 @@
dayName := string.
^ nil.
].
- (format sameAs:'d') ifTrue:[
+ ((format sameAs:'d') or:[format sameAs:'day']) ifTrue:[
day := Integer readFrom:string.
^ #day -> day
].
- (format sameAs:'m') ifTrue:[
+ ((format sameAs:'m') or:[format sameAs:'month']) ifTrue:[
month := Integer readFrom:string.
^ #month -> month
].
@@ -1837,21 +2027,64 @@
^ #month -> month
].
- format = 'y' ifTrue:[
+ format = 'y1900' ifTrue:[
+ year := Integer readFrom:string.
+ year < 100 ifTrue:[
+ ^ #year -> (year + 1900)
+ ].
+ ^ #year -> year
+ ].
+
+ format = 'y1950' ifTrue:[
+ "shift YY into 1950..2049; for 2k support of old date strings"
+ year := Integer readFrom:string.
+ year < 100 ifTrue:[
+ year < 50 ifTrue:[
+ ^ #year -> (year + 2000)
+ ].
+ ^ #year -> (year + 1900)
+ ].
+ ^ #year -> year
+ ].
+
+ format = 'y1980' ifTrue:[
+ "shift YY into 1980..2079; for 2k support of old date strings"
+ year := Integer readFrom:string.
+ year < 100 ifTrue:[
+ year < 80 ifTrue:[
+ ^ #year -> (year + 2000)
+ ].
+ ^ #year -> (year + 1900)
+ ].
+ ^ #year -> year
+ ].
+
+ (format = 'Y') ifTrue:[
+ "shift YY into 1970..2069; for 2k support of old date strings"
+ year := Integer readFrom:string.
+ year < 100 ifTrue:[
+ year < 70 ifTrue:[
+ ^ #year -> (year + 2000)
+ ].
+ ^ #year -> (year + 1900)
+ ].
+ ^ #year -> year
+ ].
+
+ ((format = 'y') or:[format sameAs:'year']) ifTrue:[
year := Integer readFrom:string.
year < 100 ifTrue:[
^ #year -> (year + 2000)
].
^ #year -> year
].
- format = 'Y' ifTrue:[
- year := Integer readFrom:string.
- year >= 100 ifTrue:[
- ^ #year -> year
- ].
- ^ #year -> (year + 2000)
+
+ (format sameAs:'dayOfYear') ifTrue:[
+ dayOfYear := Integer readFrom:string.
+ ^ #dayOfYear -> dayOfYear
].
- self error:'unknown format specifier'
+
+ self error:'unknown format specifier: ',format
! !
!Date class methodsFor:'private-instance creation'!
@@ -3103,12 +3336,15 @@
!Date methodsFor:'printing & storing'!
addPrintBindingsTo:aDictionary
+ "see comment in addPrintBindingsTo:language:"
+
self addPrintBindingsTo:aDictionary language:nil.
!
addPrintBindingsTo:aDictionary language:languageOrNil
"private print support: add bindings for printing to aDictionary.
- languageOrNil can only be #en or nil for the current language.
+ languageOrNil can only be #en or nil for the current language setting (Smalltalk language).
+
valid format items are:
%d - day, 01..31 0-padded to length 2
%m - month, 01..12 0-padded to length 2
@@ -3121,7 +3357,17 @@
%W - week in year - unpadded
%Y - year, last 2 digits only i.e. 99, 04 (danger: year 2k bug)
+ %Y1900 - year, last 2 digits of 19YY only i.e. 99, 04 (danger: year 2k bug)
+ raises an error, if the year is not in 1900..1999
+ %Y2000 - year, last 2 digits of 20YY only i.e. 01, 04 or 15
+ raises an error, if the year is not in 2000..2099
+ %Y1950 - year, last 2 digits of 19YY or 20YY only i.e. 01, 04 or 80
+ raises an error, if the year is not in 1950..2049
+ %Y1980 - year, last 2 digits of 19YY or 20YY only i.e. 01, 04 or 80
+ raises an error, if the year is not in 1980..2079
+
%(weekDay) - day in week (1->monday, 2->tuesday, ... ,7->sunday)
+ %(dayOfYear) - day in year (1..365/366)
%(dayName) - full day name
%(DayName) - full day name, first character uppercase
@@ -3148,7 +3394,7 @@
|day ds dsPadded0 dsPaddedB month ms msPadded0 msPaddedB
year weekInYear monthName shortMonthName
- dayInWeek dayOfWeek dayName shortDayName ws wsPadded0|
+ dayInWeek dayOfWeek dayName dayOfYear shortDayName ws wsPadded0|
day := self day.
ds := day printString.
@@ -3167,6 +3413,7 @@
dayInWeek := self dayInWeek. "/ 1 .. 7
dayOfWeek := self dayOfWeek. "/ 0 .. 6
+ dayOfYear := self dayOfYear. "/ 0 .. 6
monthName := self class nameOfMonth:(self month) language:languageOrNil.
dayName := self class nameOfDay:dayInWeek language:languageOrNil.
@@ -3197,6 +3444,26 @@
aDictionary at:$M put:ms.
aDictionary at:$y put:year.
aDictionary at:$Y put:((year \\ 100) printStringLeftPaddedTo:2 with:$0).
+ aDictionary at:#Y1950 put:[
+ (year between:1950 and:2049) ifFalse:[
+ self error:'year cannot be represented'
+ ].
+ (year between:1950 and:1999) ifTrue:[
+ (year - 1900) printStringLeftPaddedTo:2 with:$0
+ ] ifFalse:[
+ (year - 2000) printStringLeftPaddedTo:2 with:$0
+ ]
+ ].
+ aDictionary at:#Y1980 put:[
+ (year between:1980 and:2079) ifFalse:[
+ self error:'year cannot be represented'
+ ].
+ (year between:1980 and:1999) ifTrue:[
+ (year - 1900) printStringLeftPaddedTo:2 with:$0
+ ] ifFalse:[
+ (year - 2000) printStringLeftPaddedTo:2 with:$0
+ ]
+ ].
aDictionary at:$w put:wsPadded0.
aDictionary at:$W put:ws.
@@ -3213,6 +3480,7 @@
aDictionary at:#weekDay put:dayInWeek.
aDictionary at:#weekday put:dayInWeek.
aDictionary at:#weekDayUS put:dayOfWeek.
+ aDictionary at:#dayOfYear put:dayOfYear.
aDictionary at:#shortDayName put:(shortDayName := self class abbreviatedNameOfDay:(self dayInWeek) language:languageOrNil).
aDictionary at:#shortdayname put:shortDayName asLowercase.
@@ -3266,6 +3534,8 @@
Date today printOn:Transcript format:'%(DayName), %D%(nth) of %(MonthName), %y'
Date today printOn:Transcript format:'%(ShortDayName), %D-%(ShortMonthName)-%y'
Date today printOn:Transcript format:'%d%m%Y' (millenium bug format - danger)
+ Date today printOn:Transcript format:'%d%m%(Y1950)' (millenium bug partial workaround format - danger)
+ Date today printOn:Transcript format:'%d%m%(Y1980)' (millenium bug partial workaround format - danger)
Date today printOn:Transcript format:'Today is the %(weekDay) day of the week'
Date today printOn:Transcript format:'Today is %(year).%(monthRoman).%D' (hungarian format)
Date today printOn:Transcript format:'Today is %(D) %(monthRoman) %y' (poland)
@@ -3273,12 +3543,15 @@
Date today printOn:Transcript format:'Today is %(D)/%(mon)-%Y' (sweden)
Date today printOn:Transcript format:'Anno domini %(yearRoman)'
Date today printOn:Transcript format:'%y年%(mon)月%d日' (select a font, which can display those chars)
+ Date today printOn:Transcript format:'%(dayOfYear)'
"
+
"short form (as in blogs like www.stackoverflow, www.superuser etc.)
Date today printOn:Transcript format:'%(MonthName) %D ''%Y'
Timestamp now printOn:Transcript format:'%(MonthName) %D ''%Y at %h:%m'
"
- "
+
+ "Squeak format spec:
String streamContents:[:s |
Date today printOn:s format:#(1 2 3 $/ 1 2)
]
@@ -3475,11 +3748,11 @@
!Date class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Date.st,v 1.170 2015-05-17 20:49:07 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Date.st,v 1.174 2015-06-06 11:18:11 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Date.st,v 1.170 2015-05-17 20:49:07 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Date.st,v 1.174 2015-06-06 11:18:11 cg Exp $'
! !
--- a/TZTimestamp.st Sat Jun 06 06:39:31 2015 +0200
+++ b/TZTimestamp.st Sun Jun 07 06:38:49 2015 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 2014 by eXept Software AG
All Rights Reserved
@@ -123,8 +125,8 @@
|ti|
"/ utcOffset negative: east of GMT
- ti := OperatingSystem computeUTCTimeAndDateFrom:(osTime - (utcOffset * 1000)).
- ti utcOffset:utcOffset.
+ ti := OperatingSystem computeUTCTimeAndDateFrom:(osTime - ((utcOffset ? 0) * 1000)).
+ ti utcOffset:(utcOffset ? 0).
^ ti
!
@@ -138,7 +140,7 @@
If utcOffset is negative, the local timezone is east of Greenwich.
If utcOffset is positive, the local timezone is west of Greenwich."
- ^ utcOffset
+ ^ utcOffset ? 0
!
utcOffset:seconds
@@ -184,7 +186,7 @@
speciesNew
^ self species basicNew
- utcOffset:utcOffset;
+ utcOffset:(utcOffset ? 0);
yourself
!
@@ -195,10 +197,10 @@
!TZTimestamp class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/TZTimestamp.st,v 1.10 2015-02-06 10:36:58 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/TZTimestamp.st,v 1.12 2015-06-06 12:42:27 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/TZTimestamp.st,v 1.10 2015-02-06 10:36:58 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/TZTimestamp.st,v 1.12 2015-06-06 12:42:27 cg Exp $'
! !
--- a/Time.st Sat Jun 06 06:39:31 2015 +0200
+++ b/Time.st Sun Jun 07 06:38:49 2015 +0200
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -187,6 +185,133 @@
"
!
+readFrom:aStringOrStream format:formatString language:languageOrNil onError:exceptionalValue
+ "return a new Time, reading a printed representation from aStream using a formatString.
+ The formatString is similar to the one used when printing.
+ On error, exceptionalValue is returned.
+ If exceptionalValue is a one-arg block, an error message is passed as argument.
+ Format:
+ %h hours, 00..23 (i.e. european) 0-padded to length 2
+ %u hours, 00..12 (i.e. us) 0-padded to length 2
+ %m minutes, 00..59 0-padded to length 2
+ %s seconds, 00..59 0-padded to length 2
+ %i milliseconds, 000..999 0-padded to length 3
+ %a am/pm
+
+ an optional length after the % gives a field length;
+ i.e. %2h%2m%2s parses '123557' as 12:35:37
+
+ Please consider using a standard format, such as iso8601.
+ "
+
+ |hour minute second millisecond
+ utcOffset inStream formatStream error fChar format itemHandler
+ len s|
+
+ error := [:msg |
+ exceptionalValue isBlock ifTrue:[
+ ^ exceptionalValue valueWithOptionalArgument:'format error'
+ ] ifFalse:[
+ ^ exceptionalValue value
+ ].
+ ].
+
+ itemHandler := [:format |
+ |input|
+
+ input := len isNil ifTrue:[ inStream ] ifFalse:[ inStream next: len ].
+
+ ( format = 'h' or:[ format = 'H' ]) ifTrue:[
+ hour := Integer readFrom:input onError:[ error value:'invalid hour' ].
+
+ ] ifFalse:[ ( format = 'u' or:[ format = 'U']) ifTrue:[
+ hour := Integer readFrom:input onError:[ error value:'invalid hour' ].
+
+ ] ifFalse:[ ( format = 'm' or:[ format = 'M' ]) ifTrue:[
+ minute := Integer readFrom:input onError:[ error value:'invalid minute' ].
+
+ ] ifFalse:[ ( format = 's' or:[ format = 'S' ]) ifTrue:[
+ second := Integer readFrom:input onError:[ error value:'invalid second' ].
+
+ ] ifFalse:[ ( format = 'i' or:[ format = 'I' ]) ifTrue:[
+ millisecond := Integer readFrom:input onError:[ error value:'invalid millsecond' ].
+
+ ] ifFalse:[ ( format = 'tz' ) ifTrue:[
+ utcOffset := Timestamp utcOffsetFrom:input.
+ utcOffset isNil ifTrue:[ error value:'invalid timezone' ]
+ ] ifFalse:[ ( format = 'a' ) ifTrue:[
+ s := (input next:2) asLowercase.
+ s = 'am' ifTrue:[
+ (hour between:0 and:12) ifFalse:[ error value:'invalid hour' ]
+ ] ifFalse:[
+ s = 'pm' ifTrue:[
+ (hour between:1 and:12) ifFalse:[ error value:'invalid hour' ].
+ hour := hour + 12.
+ ] ifFalse:[
+ error value:'invalid am/pm'
+ ]
+ ]
+
+ ] ifFalse:[
+ error value:'unhandled format:',format
+ ]]]]]]]
+ ].
+
+ hour := 0.
+ minute := 0.
+ second := 0.
+ millisecond := 0.
+ utcOffset := 0.
+
+ inStream := aStringOrStream readStream.
+ formatStream := formatString readStream.
+
+ [formatStream atEnd] whileFalse:[
+ fChar := formatStream next.
+ fChar = Character space ifTrue:[
+ inStream peek isSeparator ifFalse:[ error value: 'format error; space expcected' ].
+ inStream skipSeparators.
+ ] ifFalse:[
+ fChar == $% ifTrue:[
+ len := nil.
+ (formatStream peek isDigit) ifTrue:[
+ len := Integer readFrom:formatStream onError:[ error value: 'format error; invalid length' ]
+ ].
+ (formatStream peek == $() ifTrue:[
+ formatStream next.
+ format := formatStream upTo:$).
+ ] ifFalse:[
+ (formatStream peek == ${) ifTrue:[
+ formatStream next.
+ format := formatStream upTo:$}.
+ ] ifFalse:[
+ (formatStream peek isLetter) ifTrue:[
+ format := formatStream nextAlphaNumericWord.
+ ] ifFalse:[
+ error value:'unhandled format:',formatStream peek
+ ]
+ ]
+ ].
+ itemHandler value:format.
+ ] ifFalse:[
+ inStream peek = fChar ifFalse:[^ error value: 'format error; ',fChar,' expcected'].
+ inStream next.
+ ]
+ ].
+ ].
+
+ ^ (self
+ hours:(hour ? 0) minutes:(minute ? 0) seconds:(second ? 0) milliseconds:millisecond)
+ + utcOffset
+
+ "
+ Time readFrom:'13:11:06' format:'%h:%m:%s' language:nil onError:[self halt]
+ Time readFrom:'131106' format:'%2h%2m%2s' language:nil onError:[self halt]
+ Time readFrom:'7:30pm EST' format:'%u:%m%a %tz' language:#en onError:[self halt]
+ Time readFrom:'7:30pm UTC' format:'%u:%m%a %tz' language:#en onError:[self halt]
+ "
+!
+
readFrom:aStringOrStream onError:exceptionBlock
"return a new Time, reading a printed representation from aStream.
If no am/pm follows the time, the string is interpreted as
@@ -707,7 +832,6 @@
"
! !
-
!Time methodsFor:'printing & storing'!
print12HourFormatOn:aStream
@@ -953,10 +1077,10 @@
!Time class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.104 2015-06-06 12:57:19 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.104 2015-06-06 12:57:19 cg Exp $'
! !
--- a/Timestamp.st Sat Jun 06 06:39:31 2015 +0200
+++ b/Timestamp.st Sun Jun 07 06:38:49 2015 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -781,6 +783,7 @@
%d - day
%D - day
%(day) - day
+ %(dayOfYear) - 1..365/366
%(month) - month
@@ -792,6 +795,8 @@
72..99 map to 1972..1999;
%Y1900 - year, last 2 digits only, map to 1900..1999
%Y2000 - year, last 2 digits only, map to 2000..2099
+ %Y1950 - year, last 2 digits only, map to 1950..2049
+ %Y1980 - year, last 2 digits only, map to 1980..2079
an optional length after the % gives a field length;
i.e. %2h%2m%2s parses '123557' as 12:35:37
@@ -800,14 +805,14 @@
Please consider using a standard format, such as iso8601.
"
- |day month year
+ |day month year dayOfYear monthAndDay
hour minute second millisecond
utcOffset inStream formatStream error fChar format itemHandler
len now s|
error := [:msg |
exceptionalValue isBlock ifTrue:[
- ^ exceptionalValue valueWithOptionalArgument:'format error; space expcected'
+ ^ exceptionalValue valueWithOptionalArgument:'format error'
] ifFalse:[
^ exceptionalValue value
].
@@ -815,6 +820,7 @@
itemHandler := [:format |
|input|
+
input := len isNil ifTrue:[ inStream ] ifFalse:[ inStream next: len ].
( #('d' 'D' 'day' ) includes:format ) ifTrue:[
@@ -829,22 +835,43 @@
] ifFalse:[ ( format = 'Y' ) ifTrue:[
year := Integer readFrom:input onError:[ error value:'invalid year' ].
(year between:0 and: 99) ifFalse:[ error value:'invalid year' ].
- (year between:0 and:71) ifTrue:[
+ (year < 70) ifTrue:[
+ year := year + 2000
+ ] ifFalse:[
year := year + 1900
- ] ifFalse:[
- year := year + 2000
]
] ifFalse:[ (format = 'monthName') ifTrue:[
s := input nextMatching:[:c | c isLetter] thenMatching:[:c | c isLetter].
month := Date indexOfMonth:s asLowercase language:languageOrNil
- ] ifFalse:[ ( format = 'Y1900' ) ifTrue:[
+ ] ifFalse:[ (format = 'dayOfYear') ifTrue:[
+ dayOfYear := Integer readFrom:input onError:[ error value:'invalid day of year' ].
+
+ ] ifFalse:[ ( format sameAs: 'Y1900' ) ifTrue:[
year := Integer readFrom:input onError:[ error value:'invalid year' ].
(year between:0 and: 99) ifFalse:[ error value:'invalid year' ].
year := year + 1900
- ] ifFalse:[ ( format = 'Y2000' ) ifTrue:[
+ ] ifFalse:[ ( format sameAs: 'Y1950' ) ifTrue:[
+ year := Integer readFrom:input onError:[ error value:'invalid year' ].
+ (year between:0 and: 99) ifFalse:[ error value:'invalid year' ].
+ (year between:0 and: 49) ifTrue:[
+ year := year + 2000
+ ] ifFalse:[
+ year := year + 1900
+ ]
+
+ ] ifFalse:[ ( format sameAs: 'Y1980' ) ifTrue:[
+ year := Integer readFrom:input onError:[ error value:'invalid year' ].
+ (year between:0 and: 99) ifFalse:[ error value:'invalid year' ].
+ (year between:0 and: 79) ifTrue:[
+ year := year + 2000
+ ] ifFalse:[
+ year := year + 1900
+ ]
+
+ ] ifFalse:[ ( format sameAs: 'Y2000' ) ifTrue:[
year := Integer readFrom:input onError:[ error value:'invalid year' ].
(year between:0 and: 99) ifFalse:[ error value:'invalid year' ].
year := year + 2000
@@ -882,8 +909,8 @@
] ifFalse:[
error value:'unhandled format:',format
- ]]]]]]]]]]]]]]
- ].
+ ]]]]]]]]]]]]]]]]]
+ ].
hour := 0.
minute := 0.
@@ -931,14 +958,29 @@
year isNil ifTrue:[
year := (now := Timestamp now) year
].
-
- ^ (self year:year month:month day:day hour:(hour ? 0) minute:(minute ? 0) second:(second ? 0) millisecond:millisecond) + utcOffset
+
+ dayOfYear notNil ifTrue:[
+ monthAndDay := Date monthAndDayFromDayInYear:dayOfYear forYear:year.
+ month := (monthAndDay at:1).
+ day := (monthAndDay at:2).
+ ].
+
+ ^ (self
+ year:year month:month day:day
+ hour:(hour ? 0) minute:(minute ? 0) second:(second ? 0) millisecond:millisecond)
+ + utcOffset
"
Timestamp readFrom:'20-2-1995 13:11:06' format:'%day-%month-%year %h:%m:%s' language:nil onError:[self halt]
Timestamp readFrom:'20021995131106' format:'%2d%2month%4y%2h%2m%2s' language:nil onError:[self halt]
+ Timestamp readFrom:'200295131106' format:'%2d%2month%2y%2h%2m%2s' language:nil onError:[self halt]
+ Timestamp readFrom:'200260131106' format:'%2d%2month%2(y1900)%2h%2m%2s' language:nil onError:[self halt]
+ Timestamp readFrom:'200260131106' format:'%2d%2month%2(y2000)%2h%2m%2s' language:nil onError:[self halt]
+ Timestamp readFrom:'200260131106' format:'%2d%2month%2(y1950)%2h%2m%2s' language:nil onError:[self halt]
+ Timestamp readFrom:'200260131106' format:'%2d%2month%2(y1980)%2h%2m%2s' language:nil onError:[self halt]
Timestamp readFrom:'March 7 2009 7:30pm EST' format:'%monthName %day %year %u:%m%a %tz' language:#en onError:[self halt]
Timestamp readFrom:'March 7 2009 7:30pm UTC' format:'%monthName %day %year %u:%m%a %tz' language:#en onError:[self halt]
+ Timestamp readFrom:'2015103' format:'%4y%3dayOfYear' onError:[self halt]
"
!
@@ -2384,11 +2426,19 @@
super addPrintBindingsTo:dict language:languageOrNil.
date year == Date today year ifTrue:[
- dict at:#yearOrTime put:('%h:%m' expandPlaceholdersWith:dict).
+ dict at:#yearOrTime put:('%h:%m' expandPlaceholdersWith:dict).
].
"
- Timestamp now addPrintBindingsTo:Dictionary new inspect language:nil
+ |d|
+ d := Dictionary new.
+ Timestamp now addPrintBindingsTo:d language:nil.
+ d inspect.
+ "
+
+ "used by:
+ Timestamp now printStringFormat:'%y-%m-%d'
+ Timestamp now printStringFormat:'%(dayOfYear)'
"
!
@@ -3908,11 +3958,11 @@
!Timestamp class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Timestamp.st,v 1.215 2015-06-05 17:41:37 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Timestamp.st,v 1.220 2015-06-06 12:57:00 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Timestamp.st,v 1.215 2015-06-05 17:41:37 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Timestamp.st,v 1.220 2015-06-06 12:57:00 cg Exp $'
! !
--- a/UtcTimestamp.st Sat Jun 06 06:39:31 2015 +0200
+++ b/UtcTimestamp.st Sun Jun 07 06:38:49 2015 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 2011 by eXept Software AG
All Rights Reserved
@@ -11,6 +13,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
Timestamp subclass:#UtcTimestamp
instanceVariableNames:''
classVariableNames:''
@@ -72,6 +76,8 @@
!
utcOffset
+ "I am an UTC timestamp, so there is no offset"
+
^ 0
!
@@ -142,10 +148,10 @@
!UtcTimestamp class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/UtcTimestamp.st,v 1.15 2014-11-26 09:32:11 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UtcTimestamp.st,v 1.16 2015-06-06 12:42:18 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/UtcTimestamp.st,v 1.15 2014-11-26 09:32:11 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UtcTimestamp.st,v 1.16 2015-06-06 12:42:18 cg Exp $'
! !