develooper Front page | perl.datetime | Postings from July 2017

Re: How to check if a DateTime is invalid (again - but this timewithout using eval)?

Thread Previous | Thread Next
From:
Eric Brine
Date:
July 2, 2017 20:02
Subject:
Re: How to check if a DateTime is invalid (again - but this timewithout using eval)?
Message ID:
CALJW-qG5q9hF3sCvd5QwcqUC-SCVvFCOSUL6_AqdnkC14rvZCQ@mail.gmail.com
`eval BLOCK` is very different `eval EXPR`.

The latter involves the need to generate Perl code, and ask the related
risks. That's not the case for the former, which is the right tool for the
job here.

On Jul 2, 2017 6:03 AM, "Binarus" <lists@binarus.de> wrote:

Dear all,

I am a long time user of Perl and have done several web application
back-ends based on it. But I haven't touched eval yet, mainly because I
have got the impression that it is a very complex beast with many side
effects and that using it is slow, unsafe or unclean in a certain sense.
Furthermore, I just didn't need it until now. To make a long story
short, I'd like to keep avoiding it.

Now, I am working on an application which heavily uses DateTime (mainly
for converting between users' time zones and the UTC time zone where the
math is done). Due to the character of the UI, it is inevitable that the
application will have to process invalid (i.e. formally correct, but
actually non-existent) date-times (like the 6th of April in 2003 at
02:30 in the America/Chicago time zone, to cite the example from the
DateTime documentation).

My problem is how I could detect such invalid (i.e. non-existent)
date-times. Of course, I have tried to do my homework before asking here
and have done a lot of research:

- Most people recommend to "catch the error" DateTime throws when
encountering such date-times, but if I got it right, that always
involves eval, even when using modules like Try:Tiny and the like, so I
don't want to do that.

- Some people recommend using undocumented functions / data arrays of
DateTime::Timezone to get the periods from the time zone database and
use that data to make an own algorithm to check whether a certain
date-time in a certain time-zone does exist or not. Dave explicitly
recommends against that approach, though, and I will follow his advice.

- Date::Manip::TZ -> all_periods() seems to provide a clean way to get
the period information for a certain time zone and year. But even when I
know the periods, I still have to make my own algorithm for checking the
date-time in question (which means reinventing a great part of the
wheel). Additionally, including another module into my application
solely to solve that problem seems a bit oversized.

So I still have the hope that Dave eventually is willing to solve that
problem. I am very well understanding that it might not be wise to
change the DateTime -> new() function accordingly (for compatibility and
technical reasons).

But (in my naive thinking) making a new function for testing if a
date-time exists probably is easy; after all, the respective tests
already are in DateTime (otherwise, it couldn't throw an error / die
when encountering non-existent date-times, could it?). So, I'd like to
ask if there is any chance for the following to happen :-)

1) Clone the DateTime -> new() function and name the new function
DateTime -> date_time_exists(). At this point, both functions still are
exactly identical, including the parameters.

2) Change the code of the DateTime -> date_time_exists() function in the
following way:

a) Return a boolean value instead of a date-time object.

b) At all places where it dies / throws an error due to the date-time
being invalid, just return false instead of dying / throwing an error.

c) If it reaches its end without having returned false, return true.

Of course, testing a date-time (using -> date_time_exists()) before
actually getting it (using -> new()) will cause a performance penalty,
and there will be a lot of unnecessary code in -> date_time_exists()
(which could be cleaned up later, though), and if there is a bug in ->
new(), it is probably in -> date_time_exists() as well.

On the other hand, I don't care about the performance penalty, and we
finally would have a clean and quick solution for a problem affecting
many people.

Indeed, I have found dozens of threads on various sites and lists
regarding this subject, most of them with the first answer recommending
using eval to catch DateTime's errors, the next answer / comment
explaining how complex, slow and dangerous this is and under which
circumstances it will fail, the next answer / comment recommending using
Try::Tiny to avoid those problems, the next answer explaining why you
shouldn't use Try::Tiny, the next answer recommending using TryCatch
instead of Try::Tiny, and so on (exaggerated by intention - I think
we've got the idea).

So I ultimately would like to be able to check if a date-time is valid
*before* calling DateTime -> new(), meaning that I don't have to "catch
errors".

What do you think about it?

Thank you very much!

Binarus

P.S. If there is another module which provides functions for such tests,
please let me know (but even in this case, I would highly appreciate if
DateTime would be extended accordingly; it is extremely reliable and
well documented - thanks Dave!)

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About