Re: DateTime parse(), parser()
On Wed, 16 Jul 2003, Iain Truskett wrote: What do people think parsers should return if they can't parse? And what if they do parse, but DateTime doesn't want to create an object of the appropriate specification? Should we wrap our methods in evals and return undef? Should we just throw errors? I'm a big fan of throwing errors, since it forces the callers to actually handle them. Just returning undef leads to this: my $dt = $parser-parse('this is not a date'); do_something_with_date($dt); and then mysterious failures later on. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
At 3:42 PM +1000 16/7/03, Iain Truskett wrote: What do people think parsers should return if they can't parse? And what if they do parse, but DateTime doesn't want to create an object of the appropriate specification? DateTime::Undef :) If all modules return DateTime::Undef and all modules handle it when passed it, then everything flows. If we return undef, then we need to make sure all methods can handle undef parameters cleanly. Of course, we really can't do this because: undef-set( day=$day ) is an error .. no matter what! However: $undef = new DateTime::Undef; $undef-set( day=$day ); just returns DateTime::Undef; Cheers! Rick -- There are 10 kinds of people: those that understand binary, and those that don't. The day Microsoft makes something that doesn't suck is the day they start selling vacuum cleaners Write a wise proverb and your name will live forever. -- Anonymous
Re: DateTime parse(), parser()
On Wed, 16 Jul 2003, Rick Measham wrote: At 3:42 PM +1000 16/7/03, Iain Truskett wrote: What do people think parsers should return if they can't parse? And what if they do parse, but DateTime doesn't want to create an object of the appropriate specification? DateTime::Undef :) If all modules return DateTime::Undef and all modules handle it when passed it, then everything flows. Flows is one word for it. If we return undef, then we need to make sure all methods can handle undef parameters cleanly. Of course, we really can't do this because: undef-set( day=$day ) is an error .. no matter what! However: $undef = new DateTime::Undef; $undef-set( day=$day ); just returns DateTime::Undef; And this is a good thing because it will induce incredibly mysterious errors in the end user's code? Fatal errors are a _good_ thing. Forging ahead with bad data and _not_ getting errors is a very, very, very bad thing. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
* Dave Rolsky ([EMAIL PROTECTED]) [16 Jul 2003 16:11]: [...] Fatal errors are a _good_ thing. Forging ahead with bad data and _not_ getting errors is a very, very, very bad thing. autarch++ Despite most of the _innards_ of Builder returning undef when they hit problems, all the external methods throw errors, since until that point whether it's actually bad data is not known. cheers, -- Iain.
Re: DateTime parse(), parser()
On Wed, 16 Jul 2003, Iain Truskett wrote: What do people think parsers should return if they can't parse? And what if they do parse, but DateTime doesn't want to create an object of the appropriate specification? Should we wrap our methods in evals and return undef? Should we just throw errors? At 1:06 AM -0500 16/7/03, Dave Rolsky replied: I'm a big fan of throwing errors, since it forces the callers to actually handle them. Just returning undef leads to this: my $dt = $parser-parse('this is not a date'); do_something_with_date($dt); and then mysterious failures later on. I'm an anti-fan of die. Die requires wrapping in eval or parsing the user's input before passing to -parse_datetime, which is just crazy. We should only throw errors on programmer error. For example: $dt-set( weekday = 'Friday' ); should error because there's no 'weekday' parameter for set(). However, we should return DateTime::Undef on user error: $dt-set( day = 'Twenty-two' ); because it means that we can now test for DateTime::Undef, letting set() do the parsing of the user's input. Just another $0.02 Cheers! Rick -- There are 10 kinds of people: those that understand binary, and those that don't. The day Microsoft makes something that doesn't suck is the day they start selling vacuum cleaners Write a wise proverb and your name will live forever. -- Anonymous
Re: DateTime parse(), parser()
Dave Rolsky [EMAIL PROTECTED] schrieb/wrote: Fatal errors are a _good_ thing. Forging ahead with bad data and _not_ getting errors is a very, very, very bad thing. DBI has an option RaiseError. We could: . have a variable $DateTime::AutoRaise (which should be overridden using local) . have a class factory (in DT::Format) that does the correct thing given input from parsers, i.e.: . returns a DateTime object if everything is correct. . returns a DateTime::Partial object if some data is missing. . returns a DateTime::Undef or throws an exception if there's incorrect data, depending on the setting of $DateTime::AutoRaise. Parsers should only parse; all of the above is common code that should not be re-implemented in all parsers. Claus -- http://www.faerber.muc.de
Re: DateTime parse(), parser()
Actually, DT::Undef is just a special case of the proposed DT::Partial object. Not really - it's totally different state. Any partial time can already be expressed with the current DT class. We just need a means to specify the precision. -J --
Re: DateTime parse(), parser()
Rick Measham [EMAIL PROTECTED] schrieb/wrote: Right, they won't bother using the eval (at first) and so will be forced to deal with data problems. Why is that bad? Same with not using $dt-is_undef. At least the programme fails and prints an error message instead of silently using wrong data. Claus -- http://www.faerber.muc.de
Re: DateTime parse(), parser()
On Wed, Jul 16, 2003 at 10:15:46AM -0400, John Siracusa wrote: [snip] IMO. Also, I don't think DT::Infinite is in the same boat, because that is a legitimate date (that DT::F::Simple must parse, BTW: /^([-+])?inf(?:inity)?$/i). Returning DT::Infinite is not an error! Is infinity really a simple date? I think no. Anyone else want to weigh in? -ben
Re: DateTime parse(), parser()
On Wed, 16 Jul 2003, John Siracusa wrote: Here's my take on handling parse errors, and error handling in general. 1. I don't like to (unconditionally) die from within libraries except for conditions that are totally avoidable. For example, I die if you forget to send a required argument. But I would not die in a parse() function that is expected to handle user-created input! That would force everyone to use an exception-handling style of error checking just to use your modules, which is not nice. Yeah, I can buy this, since parsing is inherently something that can fail, and it often need not be fatal, because it doesn't indicate a usage error, as opposed to bad parameters. 2. I use plain old undef as my error return value, but I sometimes document the methods saying that any false value is an indication that there was an error. This works in all methods that return objects (which is most of the ones I write, and any parsing method in DT). This also makes sense. 3. I make sure I store some sort of sensible error message or code somewhere convenient, letting the user of the library know why something failed. Even if it's only Invalid date: 'foobar', it goes a long way towards making debugging easier. I think this system gives the most flexibility to the user of a library. Examples: # Use fatal errors $dt = DateTime-parse(...) or die DateTime-error; $dt-parse(...) or die $dt-error; # Use non-fatal errors if($dt = DateTime-parse(...)) { ... } else { warn DateTime-error } if($dt-parse(...)) { ... } else { warn $dt-error } # Use exception handling eval { $dt = DateTime-parse(...) or die DateTime-error; $dt-parse(...) or die $dt-error; ... }; if(@$) { ... } Finally, I want to immediately help anyone who does this: $dt = DateTime-parse(...); $dt-set(...); By puking all over them right then and there. While a DT::Undef object might be useful for some, it should not be used as a return value in the case of an error. People who want to use it can just do this: $dt = DateTime-parse(...) || DateTime::Undef-new; I agree. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
On Tue, 15 Jul 2003, Joshua Hoblitt wrote: 2. My option: $day_of_month = STDIN; $dt-set( day = $day_of_month )-truncate( to = 'day' ); print Your day must be a number in the current month if $dt-is_undef; See, most people won't _bother_ with the 3rd line in option 2! They'll just go ahead and use the data. How many check to see if it is DT::Infinite? None of the parsing modules currently return that, and I'm not sure that they should. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
On Tue, 15 Jul 2003, Joshua Hoblitt wrote: We were talking about returning DT::Undef objects from parsers. So, for example, if the _format_ being parsed _defines_ an unknown or undefined date/time an object can be returned that reflects this. Simply returning undef when an object is expected is, IMHO, not a correct behavior. Sure, if the format has something for unknown, I can see the usefulness of such an object, although since undef also indicates unknown, I'm not sure that's so bad. My fear is that people will start returning DT objects set to something like -01-01T00:00:00 to indicate this case. Yeah, that'd be ugly. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
Well, I don't think that the simple is supposed to indicate simple to parse (at the moment the parser is all but simple... but I am trying to clean it up). I read it as simple formats, i.e. common formats that define the date and time in fairly straightforward ways (month names and numbers for things are fine, next week third thursday in the next month with a blue moon are not). The other problem I see is that your regexp only covers English speaking locales... I am currently using the DateTime::Locale date to get locale sensitive information for parsing month and day names. (Although AM/PM and BC/AD are a bit of a problem, I may need to add extra information somewhere). -ben On Wed, Jul 16, 2003 at 11:30:33AM -0400, John Siracusa wrote: On 7/16/03 11:21 AM, Ben Bennett wrote: On Wed, Jul 16, 2003 at 10:15:46AM -0400, John Siracusa wrote: [snip] IMO. Also, I don't think DT::Infinite is in the same boat, because that is a legitimate date (that DT::F::Simple must parse, BTW: /^([-+])?inf(?:inity)?$/i). Returning DT::Infinite is not an error! Is infinity really a simple date? I think no. Anyone else want to weigh in? Either way, I'll weigh in again! :) Of course it's simple because, in the context of DT::F::Simple, simple means simple to parse. And this is pretty darned simple, IMO: if(/^([-+])?inf(?:inity)?$/i) { if($1 eq '-') { return DateTime::Infinite::Past-new; } return DateTime::Infinite::Future-new; } -John
Re: DateTime parse(), parser()
On Tuesday, July 15, 2003, at 11:11 PM, Rick Measham wrote: I'm an anti-fan of die. Die requires wrapping in eval or parsing the user's input before passing to -parse_datetime, which is just crazy. We should only throw errors on programmer error. For example: $dt-set( weekday = 'Friday' ); should error because there's no 'weekday' parameter for set(). However, we should return DateTime::Undef on user error: $dt-set( day = 'Twenty-two' ); because it means that we can now test for DateTime::Undef, letting set() do the parsing of the user's input. This is why you use exception objects, and throw different exceptions for user errors vs. programmer error. David -- David Wheeler AIM: dwTheory [EMAIL PROTECTED] ICQ: 15726394 http://kineticode.com/ Yahoo!: dew7e Jabber: [EMAIL PROTECTED] Kineticode. Setting knowledge in motion.[sm]
Re: DateTime parse(), parser()
On 7/16/03 2:16 PM, Eugene van der Pijll wrote: Most of the formatting modules don't know what to do with infinite dates. That's a bug/feature in the formatting modules, IMO, not a reason to pretend that infinite dates don't exist. Similarly, most of the programs using DT won't use infinite dates. It is a pain to check for infinity everywhere. ...and yet you must do so anyway if you write subroutines that accept DateTime objects, but that want to reject infinite dates. I don't think infinity needs to be locale aware. Inf will not be locale aware in Perl 6, AFAIK, for example. Perl 6 is for programmers. I thought you needed the DT::F::Simple module for user input. Programmers are users too :) In this situation, you can think of it as a shorter constructor for brief/simple scripts (since the arguments to DateTime-new() are very verbose). This was another one of the motivators for DT::F::Simple, if you look back at the thread. If English users try to submit the string infinite in a web form (I doubt it, but hypothetically...), Dutch users would certainly type oneindig. I'm not really against localization in this case. I think natural language is outside the scope of DT::F::Simple. Simple things like now and today should get parsed, but not right now or the day after yesterday :) I'm just not sure how cleanly infinity will localize. And since it is a mathematical concept as well as a regular word (and probably used in the former context more often), I don't think it would be the end of the world if it wasn't localized. That's all I'm saying. -John
Re: DateTime parse(), parser()
Infinite dates do not exist. (And neither do undefined ones.) If you accept that as dates or not, they are both valid pieces of information that need to be expressed. -J --
Re: DateTime parse(), parser()
On 7/16/03 3:39 PM, Eugene van der Pijll wrote: John Siracusa schreef: On 7/16/03 2:16 PM, Eugene van der Pijll wrote: Most of the formatting modules don't know what to do with infinite dates. That's a bug/feature in the formatting modules, IMO, not a reason to pretend that infinite dates don't exist. Infinite dates do not exist. Infinite DateTime objects do, which was my point. A Format object does not have to accept every deranged monstrosity that is subclassed from DateTime. For example, my Format modules are documented to accept DateTime objects. DateTime::Infinite is a deranged monstrosity now!? Yeesh :) Regardless of your opinion of it, DateTime::Infinite is very useful to many people. this means that DT::F::Simple would try to be two things: 1) it wants to parse all common datetime strings that a (naive?) user would pass to the program. To do this, it has to be as lenient as possible, whilst being aware of locale issues, and if possible, it should be able to interpret the most likely meaning of defective input like 01/02/03. It should be able to parse such simple phrases as 'now', but not unintuitive mathematical concepts. 2) it wants to provide a shorter constructor. To do this, it should be exactly defined how formats are interpreted. Special phrases are provided to construct some special DT constructs (aka deranged monstrosities), like '+inf' and '-inf'. It is not necessary to duplicate other methods, so e.g. 'now' is not needed; DateTime::now() is perfectly adequate. Combining these two aims is perhaps possible. I never suggested that ambiguous forms should be parsed by DT::F::Simple. The two-digit years thread was started by someone else :) I think it should parse common, unambiguous, easy to parse date strings. Calling the result Simple is a chutzpah. Like I said earlier, maybe ::Basic is better. But ::Simple is how we've been discussing it so far, so I'm trying to avoid confusion :) Making it the default for DT parsing... ...is the key feature of the whole system! (That's what you were going to say, right? ;) If today is parsed, people expect tomorrow to be parsed as well Well, you could just set a policy to avoid anything that requires date math. But if you do want to accept tomorrow, DT makes it pretty easy with $dt-add(days = 1), unless I'm missing something... :) -John
Re: DateTime parse(), parser()
Joshua Hoblitt schreef: Infinite dates do not exist. (And neither do undefined ones.) If you accept that as dates or not, they are both valid pieces of information that need to be expressed. Sure. If the programmer chooses to, by choosing modules that return them. But no part of DateTime, the base module, should return these non-dates. They should only be a result of some action where it makes sense that something else than a date is returned. Specifically, the default parser should not return these things, and other parsers (the DBI ones, for example) should document that they can return DT::Undef or DT::Inf. IMHO, as always. Eugene
Re: DateTime parse(), parser()
On Wed, 16 Jul 2003, Eugene van der Pijll wrote: But no part of DateTime, the base module, should return these non-dates. They should only be a result of some action where it makes sense that something else than a date is returned. Specifically, the default parser should not return these things, and other parsers (the DBI ones, for example) should document that they can return DT::Undef or DT::Inf. I'm inclined to agree with you here. End users should not be getting back DT::Inf or DT::Undef (if the latter eventually exists) unless they explicitly declare that they are working in a domain where such things exist. This can be done by using a specific formatting module, for example for a database which can store infinite datetime values. Or by using the set math code, which definitely opens up the possibility of infinity. But otherwise, I'd prefer that the user not even have to know that DT::Infinite exists, because for _many_ people, they won't understand what it is for. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
John Siracusa schreef: On 7/16/03 3:39 PM, Eugene van der Pijll wrote: Infinite dates do not exist. Infinite DateTime objects do, which was my point. The Loch Ness monster exists. That doesn't mean that DateTime::Format::Roman should accept it. A Format object does not have to accept every deranged monstrosity that is subclassed from DateTime. For example, my Format modules are documented to accept DateTime objects. DateTime::Infinite is a deranged monstrosity now!? Yeesh :) Regardless of your opinion of it, DateTime::Infinite is very useful to many people. I must admit that at this point my analogy with the Loch Ness monster may be said to break down. I never suggested that ambiguous forms should be parsed by DT::F::Simple. Not even 04/05/2003? If today is parsed, people expect tomorrow to be parsed as well Well, you could just set a policy to avoid anything that requires date math. Is DT::truncate date math? If so, this disqualifies today... Oh, I forgot one: if now is parsed, never should be as well (returning DT::Undef). (That one is somewhat sensible to include, even.) Eugene
Re: DateTime parse(), parser()
On 7/16/03 4:17 PM, Eugene van der Pijll wrote: I never suggested that ambiguous forms should be parsed by DT::F::Simple. Not even 04/05/2003? That's not ambiguous, thanks to the handy setting in DT::F::Simple that tells it exactly how to interpret that :) If today is parsed, people expect tomorrow to be parsed as well Well, you could just set a policy to avoid anything that requires date math. Is DT::truncate date math? If so, this disqualifies today... You don't necessarily need to use truncate to handle today (e.g. It could just be documented to mean 00:00:00), but no, I wouldn't consider truncation to be date math. Oh, I forgot one: if now is parsed, never should be as well (returning DT::Undef). (That one is somewhat sensible to include, even.) ...unless you consider all such things to be deranged monstrosities! :) On 7/16/03 4:16 PM, Dave Rolsky wrote: End users should not be getting back DT::Inf or DT::Undef (if the latter eventually exists) unless they explicitly declare that they are working in a domain where such things exist. Like I said earlier, if your code accepts DateTime objects, but doesn't want to deal with infinite dates, then you've got to explicitly check for finite-ness anyway. I don't think you can just *assume*, based on a choice (default or otherwise) of DT::F:: modules, whether or not infinite dates will ever cross their (code) path. If you want to put the onus on the user to read the particular DT::F:: module's documentation to see what kinds of DateTime objects could possibly be returned, then users will have to do the same for DT::F::Simple. And in that case, DT::F::Simple just has to document what it can return. Finally, if you're just trying to go for the principle of least surprise, then I don't think a programmer would be surprised that DateTime-parse('infinity'); returns an infinite date! It's not like infinite dates are going to just start spewing fourth from DateTime-parse() randomly :) -John
Re: DateTime parse(), parser()
Eugene van der Pijll wrote: Oh, I forgot one: if now is parsed, never should be as well (returning DT::Undef). (That one is somewhat sensible to include, even.) now is a DT, or a DT function never is DT::Set-new_empty forever is DT::Set( -inf, inf ) undef is DT::Undef - Flavio S. Glock
Re: DateTime parse(), parser()
The Loch Ness monster exists. That doesn't mean that DateTime::Format::Roman should accept it. Yes it does. It should accepts Dave's organic cucumbers too. -J --
Re: DateTime parse(), parser()
* Bruce Van Allen ([EMAIL PROTECTED]) [15 Jul 2003 04:55]: [...] 6. All parsers fail (return undef) if they can't parse a string, both for good programming practice and to allow falling through to the next specified/available parser module; I'm yet to see a consistent method of handling errors in Perl modules. Whether an error is thrown or undef is returned, fall through is quite possible (eval). What do people think parsers should return if they can't parse? And what if they do parse, but DateTime doesn't want to create an object of the appropriate specification? Should we wrap our methods in evals and return undef? Should we just throw errors? [...] cheers, -- Iain.
RE: DateTime parse(), parser()
Hi John Iain On Sunday, July 13, 2003, at 08:11 PM, Iain Truskett wrote: Remember: part of the point of having the various format modules is that you can pick'n'mix. You could conceivably wrap a number of them in Builder to make your own parser that recognizes the sorts of dates you come across. I mostly I think an example of this type of thing needs to go into the FAQ. Do you have an example of doing this? come across HTTP, W3CDTF and RFC2822 dates so I'm all set =) Sure, but my main point is that I don't want to have to manually load and use parsers. I want DateTime (the class and/or individual objects) I agree with you on this. I feel that there should be a default simple parser within datetime. have a catch-all parse() method that uses the parser class of my choosing. And I want the default to be something than can handle most normal date formats, ignoring as much complexity as it takes to get into the core (even though DateTime::Format::Simple would still be its own module, and might not even be loaded until the first call to parse()) However, I'm interested in seeing your regex to see if you parse anything that might be of use to me. Would you like to share? They're super boring. Heck, these two cover almost everything I'm interested in: [snipped] Really, I'm not asking for the moon. The key features are the built-in/used by default nature and the I can handle whatever parse() method (instead of parse_date(), parse_datetime(), parse_year_and_day_but_not_month(), etc.) Since this is all so simple, I think it should be built in via the creation and default use of a DateTime::Format::Simple module and a generalized parse() class/object method for DateTime. [much snippage] John, Can I encourage you to put together a Format::Simple module and release it? I think we need something out there for very basic date parsing. There is the DateTime::Format::HTTP that comes very close ( It works great on Ingres dates/times). Or maybe the regrex that you provided can be incorporated into HTTP? What do you think? Ron Hill
Re: DateTime parse(), parser()
On 7/14/03 12:36 PM, Hill, Ronald wrote: Can I encourage you to put together a Format::Simple module and release it? I think we need something out there for very basic date parsing. There is the DateTime::Format::HTTP that comes very close ( It works great on Ingres dates/times). Or maybe the regrex that you provided can be incorporated into HTTP? I'd gladly release the DateTime::Format::Simple I whipped up, but only if there is consensus about the scope of the module and the name ::Simple. Mine is really ::DeadSimple :) I suspect someone else out there might want to use the ::Simple namespace for something slightly less simple than the handful of regexes and constant strings I posted earlier. Opinions? Also, I'm slightly confused about the responsibilities of a DateTime::Format:: module. Does such a module have to have format_* methods, or can it get by with just parse_datetime()? I'm not sure what a format_* method for ::Simple should produce... -John
RE: DateTime parse(), parser()
On Mon, 14 Jul 2003, Hill, Ronald wrote: On Sunday, July 13, 2003, at 08:11 PM, Iain Truskett wrote: Remember: part of the point of having the various format modules is that you can pick'n'mix. You could conceivably wrap a number of them in Builder to make your own parser that recognizes the sorts of dates you come across. I mostly I think an example of this type of thing needs to go into the FAQ. Do you have an example of doing this? Actually, it probably belongs directly in the Builder docs. Can I encourage you to put together a Format::Simple module and release it? I think we need something out there for very basic date parsing. There is the DateTime::Format::HTTP that comes very close ( It works great on Ingres dates/times). Or maybe the regrex that you provided can be incorporated into HTTP? Anything called DT::F::Simple should parse everything Date::Parse can parse, at least, and not _too_ much more, because it should also be reasonably fast ;) I know Graham Barr will be happy to see this, because at OSCON he asked me when the DateTime project will make his TimeDate stuff obsolete ;) -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
On 7/14/03 1:05 PM, Dave Rolsky wrote: Anything called DT::F::Simple should parse everything Date::Parse can parse, at least, and not _too_ much more, because it should also be reasonably fast ;) Great, but the $64K question is: do we then get parse() and parser() methods in DateTime, which default to use DT::F::Simple? :) -John
Re: DateTime parse(), parser()
On Mon, 14 Jul 2003, John Siracusa wrote: On 7/14/03 1:05 PM, Dave Rolsky wrote: Anything called DT::F::Simple should parse everything Date::Parse can parse, at least, and not _too_ much more, because it should also be reasonably fast ;) Great, but the $64K question is: do we then get parse() and parser() methods in DateTime, which default to use DT::F::Simple? :) Maybe. It would introduce another dependency for DateTime.pm, but OTOH it's a dependency that most folks would probably end up downloading anyway. -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
John Siracusa wrote: Great, but the $64K question is: do we then get parse() and parser() methods in DateTime, which default to use DT::F::Simple? :) A while ago, when this discussion last reared its [ugly] head, I suggested that the base class contain methods which would call an array of potentially more expensive parsers, until one returned a value other than undef. The default install would only include the smallest, fastest parser and the user could add other to the list. Thinking about it now, it would make the most sense to me to make DateTime::Format be an actual class which would dispatch to the DT::F::something modules. That way, nothing needs to be added to the DateTime class itself, if you never need parsing. John -- John Peacock Director of Information Research and Technology Rowman Littlefield Publishing Group 4501 Forbes Boulevard Suite H Lanham, MD 20706 301-459-3366 x.5010 fax 301-429-5748
Re: DateTime parse(), parser()
Thinking about it now, it would make the most sense to me to make DateTime::Format be an actual class which would dispatch to the DT::F::something modules. That way, nothing needs to be added to the DateTime class itself, if you never need parsing. Not all of the format modules will deal with ambiguous cases in the same way. This sounds dangerous and error prone. -J --
Re: DateTime parse(), parser()
On Monday, July 14, 2003 John Peacock wrote: John Siracusa wrote: Great, but the $64K question is: do we then get parse() and parser() methods in DateTime, which default to use DT::F::Simple? :) A while ago, when this discussion last reared its [ugly] head, I suggested that the base class contain methods which would call an array of potentially more expensive parsers, until one returned a value other than undef. The default install would only include the smallest, fastest parser and the user could add other to the list. Thinking about it now, it would make the most sense to me to make DateTime::Format be an actual class which would dispatch to the DT::F::something modules. That way, nothing needs to be added to the DateTime class itself, if you never need parsing. Some good ideas are converging here. Couldn't the following all be possible: 1. DT::Format as an actual class, per John S; 2. DT::Format has parse() and parser() methods; 3. DT::Format dispatches to DT::F::XXX modules, using DT::F::Simple unless the user has called parser(). 4. DateTime also has methods parse() and parser(), per John P, which simply invoke DT::Format and hand off their params to DT::F's own parse() and parser() methods; 5. If the user doesn't call parse() or parser() from DT, then DT::F and DT::F::XXX are never invoked by DT; 6. All parsers fail (return undef) if they can't parse a string, both for good programming practice and to allow falling through to the next specified/available parser module; 7. parser() -- or parsers()? -- would let the user specify which of the available DT::F::XXX modules to use, and the order with which they are tried. - Bruce __bruce__van_allen__santa_cruz__ca__
Re: DateTime parse(), parser()
On 7/14/03 2:31 PM, John Peacock wrote: Joshua Hoblitt wrote: I'm not really excited about this proposed feature. If it is included the loading of DT::F::Simple should be deferred until parse_datetime is called. That is another reason why I suggest not having the parser() and parse() methods in DT at all. For people who never need to parse random date strings, they only use DateTime; and they are done; everyone else does use DateTime::Format; as well. The latter use would then take an array of additional Format modules to use when parsing (if desired). Why not have them at all? Okay, so defer parser class loading until the last minute. Then all you have is a dozen or so more lines of code in DateTime. Is that going to kill you? :) I think this is a very important feature. If DateTime didn't have strftime() already, then maybe I'd buy the argument that DateTime is just an object representation of dates and doesn't deal with string input/output (although that'd make DateTime a lot less useful, I think). As things stand, the lack of a parse() method represents a gap in functionality, IMO. -John
Re: DateTime parse(), parser()
On Mon, 14 Jul 2003, John Siracusa wrote: That is another reason why I suggest not having the parser() and parse() methods in DT at all. For people who never need to parse random date strings, they only use DateTime; and they are done; everyone else does use DateTime::Format; as well. The latter use would then take an array of additional Format modules to use when parsing (if desired). Why not have them at all? Okay, so defer parser class loading until the last minute. Then all you have is a dozen or so more lines of code in DateTime. Is that going to kill you? :) No, but it might kill me ;) I'm getting concerned about DateTime bloating, not so much in terms of code, but in terms of features. Every feature requires more docs, and more docs means that it becomes harder and harder to figure out how to do the one thing _you_ want DT.pm to do. I think this is a very important feature. If DateTime didn't have strftime() already, then maybe I'd buy the argument that DateTime is just an object representation of dates and doesn't deal with string input/output (although that'd make DateTime a lot less useful, I think). As things stand, the lack of a parse() method represents a gap in functionality, IMO. Yeah, maybe ... -dave /*=== House Absolute Consulting www.houseabsolute.com ===*/
Re: DateTime parse(), parser()
On 7/14/03 3:36 PM, Dave Rolsky wrote: I'm getting concerned about DateTime bloating, not so much in terms of code, but in terms of features. Every feature requires more docs, and more docs means that it becomes harder and harder to figure out how to do the one thing _you_ want DT.pm to do. DT is only as complex as it needs to be, IMO :) And a good examples or tutorial section in the docs will go a long way towards letting users quickly and easily figure out how to do most common tasks. Of course, one of those common tasks is probably going to be parsing simple date formats. As a user, would you rather be told, Go explore the various the DT::F::* modules until you find what you need. Then download and install that module, load it, and use it to parse your dates. Then come back to these docs to learn more about those date objectsor...You can probably just use parse() if your date formats are simple. Here's an example, and here's a link to the parse() entry in this document. If your dates are more complex, then see the DT::F::* modules and the parser() method. I think this is a very important feature. If DateTime didn't have strftime() already, then maybe I'd buy the argument that DateTime is just an object representation of dates and doesn't deal with string input/output (although that'd make DateTime a lot less useful, I think). As things stand, the lack of a parse() method represents a gap in functionality, IMO. Yeah, maybe ... Search your feelings, you know it to be true! :) -John
Re: DateTime parse(), parser()
On 7/14/03 7:00 PM, Iain Truskett wrote: My only qualm is the default American bias of the second regex. Right, which is why I mentioned some sort of mode/setting. But it'd still default to US, so there ;) Heh, maybe it'd look at your current time zone to pick the default, or is that too clever by half? :) I'd probably vote for DateTime::Format::HTTP as it copes with a lot of the common formats. Poaching from Date::Parse, as suggested by Dave (I think), is my favorite idea for DT::F::Simple's scope so far. -John
Re: DateTime parse(), parser()
John Siracusa schreef: All the various DateTime::Format::* modules are nice, but I've been thinking that it would be even nicer if DateTime had some sort of rudimentary parsing built in. I agree with this; the DateTime constructor tends to get a little verbose. However, I don't quite agree with your implementation ideas. 1/20/2002 1:02 p.m. (okay, maybe a Euro-mode for dd/mm/ :) A parser that can parse this format correctly should not be called Simple. As you say, it has to have a US and a Euro mode at least; the default DateTime parser should be simple enough to need no configuration. IOW, DateTime::Format::Simple should handle at least 90% of the dates a user is likely to encounter (or a person is likely to enter). If you want a parser that can handle 90% of all dates, call it DateTime::Format::HideouslyComplex. I know I'm already tired of picking and loading DateTime::Format::* classes The answer to this would be to have a Format class which can do everything, not to have it included in DateTime. You can't have a parser that magically parses everything, without heavy configuration for amiguous cases. IMHO, the reason a parser is needed in DateTime is the verbosity of the constructor. To define a date I always need 2 lines, which screws up the formatting/indenting of the program. A shorter contructor would be nice. My suggestion would be to have a small, very restrictive parse_datetime method, which is more-or-less the reverse of the datetime() method. I suggest: sub parse_datetime { my ($self, $date) = @_; if ($date ~= /^(-?\d{4})# year (\D?)# optional date separator (\d\d) # month \2 # date sep again (\d\d) # day [T ]? (\d\d) # hour (\D?)# optional time separator (\d\d) # minute \6 # time sep again (\d\d) # second $/x) { my ($y, $m, $d, $h, $min, $s) = ($1, $3, $4, $5, $7, $8); return DateTime-new(year = $y, month = $m, day = $d, hour = $d, minute = $min, second = $s); } return; } This would make it possible to create dates in a compact but understandable way: $dt = DateTime-parse_datetime( 2003-07-13T12:38:00 ); I wouldn't use this method for user input, but only to create fixed dates in my programs. Eugene
Re: DateTime parse(), parser()
On 7/13/03 6:47 AM, Eugene van der Pijll wrote: 1/20/2002 1:02 p.m. (okay, maybe a Euro-mode for dd/mm/ :) A parser that can parse this format correctly should not be called Simple. As you say, it has to have a US and a Euro mode at least; the default DateTime parser should be simple enough to need no configuration. I don't think it would be complex at all. There's only one setting! :) IOW, DateTime::Format::Simple should handle at least 90% of the dates a user is likely to encounter (or a person is likely to enter). If you want a parser that can handle 90% of all dates, call it DateTime::Format::HideouslyComplex. See above. It's like 4 or 5 regexes for DateTime::Format::Simple. I know, because I have a DateTime wrapper that parses these formats, it it covers about *99.9%* of the date strings I encounter, including user input in web forms and such. -John
Re: DateTime parse(), parser()
John Siracusa schreef: All the various DateTime::Format::* modules are nice, but I've been thinking that it would be even nicer if DateTime had some sort of rudimentary parsing built in. On Sun, 2003-07-13 at 20:47, Eugene van der Pijll wrote: I agree with this; the DateTime constructor tends to get a little verbose. However, I don't quite agree with your implementation ideas. [snip] My suggestion would be to have a small, very restrictive parse_datetime method, which is more-or-less the reverse of the datetime() method. [snip] $dt = DateTime-parse_datetime( 2003-07-13T12:38:00 ); I wouldn't use this method for user input, but only to create fixed dates in my programs. Yup, this all looks excellent. Unless your input comes from a user or from a file or some other source this contructor would be great. I often enter a date by hand that is a static date, with this I can do it quickly. Cheers! Rick
Re: DateTime parse(), parser()
On Sunday, July 13, 2003, at 08:11 PM, Iain Truskett wrote: Remember: part of the point of having the various format modules is that you can pick'n'mix. You could conceivably wrap a number of them in Builder to make your own parser that recognises the sorts of dates you come across. I mostly come across HTTP, W3CDTF and RFC2822 dates so I'm all set =) Sure, but my main point is that I don't want to have to manually load and use parsers. I want DateTime (the class and/or individual objects) have a catch-all parse() method that uses the parser class of my choosing. And I want the default to be something than can handle most normal date formats, ignoring as much complexity as it takes to get into the core (even though DateTime::Format::Simple would still be its own module, and might not even be loaded until the first call to parse()) However, I'm interested in seeing your regexen to see if you parse anything that might be of use to me. Would you like to share? They're super boring. Heck, these two cover almost everything I'm interested in: # mm dd [hh:mm[:ss[.nnn]]] [am/pm]($year, $month, $mday, $hours, $mins, $secs, $fsecs, $ampm) = /^(\d{4})\s*-?\s*(\d{2})\s*-?\s*(\d{2})\s*(?:- ?\s*(\d{1,2}):?(\d{2})(?::?(\d{2}))?)?(?:\.(\d+))?(?:\s*([aApP]\.?[mM]\. ?))?$/ # mm/dd/, mm-dd-, [hh:mm[:ss[.nnn]]] [am/pm] ($month, $mday, $year, $hours, $mins, $secs, $fsecs, $ampm) = m#^(\d{1,2})[-/](\d{1,2})[-/ ](\d{4})(?:\s+(\d{1,2}):(\d{2})(?::(\d{2}))?)?(?:\.(\d+))?(?:\s*([aApP]\ .?[mM]\.?))?$#)) (Post-processing to handle am/pm and fsecs correctly omitted) To this I just add now, today (meaning 00:00:00), +/-infinity, and a no-op for things that are already DateTime objects. This, believe it or not, covers almost everything I expect a user to enter in a form (ignoring excess whitespace stripping and such, which happens earlier), as well as everything I expect to read from a file or whatever. Really, I'm not asking for the moon. The key features are the built-in/used by default nature and the I can handle whatever parse() method (instead of parse_date(), parse_datetime(), parse_year_and_day_but_not_month(), etc.) Since this is all so simple, I think it should be built in via the creation and default use of a DateTime::Format::Simple module and a generalized parse() class/object method for DateTime. For kicks, I just threw this into DateTime.pm use vars qw($VERSION $PARSER); ... use DateTime::Format::Simple(); # pre-loading in this case use constant DEFAULT_PARSER_CLASS = 'DateTime::Format::Simple'; ... sub parser { my $self = shift; if(ref $self) { return $self-{'parser'} = shift if(@_); return $self-{'parser'} ||= $PARSER ||= DEFAULT_PARSER_CLASS; } return $PARSER = shift if(@_); return $PARSER ||= DEFAULT_PARSER_CLASS; } sub parse { my $dt; eval { $dt = $_[0]-parser-parse_datetime($_[1]) }; return undef if($@); return $_[0] = $dt if(ref $_[0]); return $dt; } and then spent 5 minutes writing a bare bones implementation of DateTime::Format::Simple using the regexes above. And behold, simple things are easy: $dt = DateTime-parse('5/29/1945'); $dt-parse('2002-03-05 1:02 a.m.'); and hard things are possible: DateTime-parser('DateTime::Format::ReallyComplex'); $dt = DateTime-parse('the 20th of september, nineteen seventy-five, midnight'); $dt-parse('the day after tomorrow'); $dt-parse('my birthday'); # ;) -John