Stef, I don't care too much, and I have described how I will handle it if it again arises in my work. To do what you are describing, there needs to be a second argument specifying the pivot year for the cleanup/guess. A useful variant would be to specify instead the date on which the data was recorded, with an algorithm to arrive at a likely pivot date. Bill -----Original Message----- From: pharo-project-bounces@lists.gforge.inria.fr [mailto:pharo-project-bounces@lists.gforge.inria.fr] On Behalf Of Stéphane Ducasse Sent: Sunday, January 17, 2010 9:36 AM To: Pharo-project@lists.gforge.inria.fr Subject: Re: [Pharo-project] Date fromString: '6-Jan-10' Thanks david Now I think that we could have Date readFromTwoDigitYear: or something like that. And that Date readFromString: always reads a coherent 4 digits year.
This seems to have been more controversial than I expected. I'm going to write this post in which I will:
- try to make the case for supporting 2-digit years in some sensible way - answer some of the counter-arguments and questions that people have raised
... at which point I intend to withdraw, and the community will no doubt reach some sensible conclusion.
David
The case for accepting 2-digit years is, I think, very simple: it's useful. Like it or not, data sometimes comes that way and this has to be dealt with.
Granted, this means that we have to introduce some heuristic to guess which century is intended.
But we can have clever vs. explicit readFrom: '06-jan-30' what is it 1930 or 2030 readFrom: '06-jan-30' usingBaseForYear: 2000 -> 2030 I prefer explicit because it produces more robust code.
However, I don't see that this is so bad. Amongst the possible approaches are:
- Following the Posix standard for strptime, the date is assumed to be between 1969 and 2068 (see http://www.opengroup.org/onlinepubs/009695399/functions/strptime.html). Python goes this way, for example.
- the date is assumed to be between 80 years in the past and 20 years in the future (eg Java's SimpleDateFormat, see http://java.sun.com/javase/7/docs/api/java/text/SimpleDateFormat.html)
- allow the 100 year-period in which 2-digit years will be placed to be specified (eg the Java SimpleDateFormat also allows this)
. Year: For formatting, if the number of pattern letters is 2, the year is truncated to 2 digits; otherwise it is interpreted as a number. For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the SimpleDateFormat instance is created. For example, using a pattern of "MM/dd/yy" and a SimpleDateFormat instance created on Jan 1, 1997, the string "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" would be interpreted as May 4, 1964. During parsing, only strings consisting of exactly two digits, as defined by Character.isDigit(char), will be parsed into the default century. Any other numeric string, such as a one digit string, a three or more digit string, or a two digit string that isn't all digits (for example, "-1"), is interpreted literally. So "01/02/3" or "01/02/003" are parsed, using the same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC. http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html
Now I will address some concerns that people have raised.
The first is essentially aesthetic: this kind of cleverness should not be there, and everyone should always use four-digit years. I've some sympathy with this, and it would be wonderful if everyone was as principled as we are. But, alas, it is not so! My judgment is that it's worth a little ugliness to be able to deal with the common case of two-digit years.
A second objection was that the code was right all along: '6-Jan-10' should correctly be parsed as 6th January 1910. This seems to me peculiar. I understand a position that says that two-digit years should not be accepted at all, but arguing that they should be accepted and should be interpreted to be 100 or more years ago... well, this seems unlikely to be the most useful approach.
A third objection was that this is the thin end of the wedge: if we start accepting two-digit years, who knows where the madness will end? We will have to deal with all kinds of crazy situation!
I think that this objection is just wrong. Noone is arguing for three-digit dates, or hexadecimal dates, or any other crazy stuff. Two-digits are commonplace. Other crazy things are not commonplace. Let's draw the line where it makes sense to draw the line: to my mind handling two-digit years clearly falls on the 'useful' side and not the 'crazy' side.
Finally, I must note the irony of one poster declaring that we should only accept well-formed strings, and pointing us at RFC822 for reference. Years in RFC822 are defined to have two digits. The RFC does not say what century they should fall in. (This has been obsoleted by RFC2822, which uses four-digit years).
"Stéphane Ducasse" <stephane.ducasse@inria.fr> wrote in message news:78E0F3D1-D169-43D9-B12E-6C9D4E2860C5@inria.fr...
hi guys
can one of you give a look at the this fix because I'm confused. Kernel-DavidHotham.538
year < 20 ifTrue: [year := 2000 + year] was year < 10 ifTrue: [year := 2000 + year]
both solutions look strange to me.
http://code.google.com/p/pharo/issues/detail?id=1749
readFrom: aStream "Read a Date from the stream in any of the forms: <day> <monthName> <year> (5 April 1982; 5-APR-82) <monthName> <day> <year> (April 5, 1982) <monthNumber> <day> <year> (4/5/82) <day><monthName><year> (5APR82)" | day month year | aStream peek isDigit ifTrue: [day := Integer readFrom: aStream]. [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. aStream peek isLetter ifTrue: ["number/name... or name..." month := (String new: 10) writeStream. [aStream peek isLetter] whileTrue: [month nextPut: aStream next]. month := month contents. day isNil ifTrue: ["name/number..." [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. day := Integer readFrom: aStream]] ifFalse: ["number/number..." month := Month nameOfMonth: day. day := Integer readFrom: aStream]. [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1]. year := Integer readFrom: aStream.
year < 20 ifTrue: [year := 2000 + year] ifFalse: [ year < 1900 ifTrue: [ year := 1900 + year]].
^ self year: year month: month day: day
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project