[REBOL] Re: Question about date? function
From: joel::neely::fedex::com at: 13-Oct-2001 8:53
Hi, Brock,
Brock & Janet wrote:
> Carl,
> Thanks. I see how this works. I guess the date? function isn't
> really processing the date and is just reporting back validity
> for the datatype query...
>
Carl's already done a great job with the original question, so I'm
just gilding the lilly...
May I suggest thinking about DATE? a little differently from your
wording above? The reason is that "validity" sounds (at least to
my ear) more like some kind of before-the-fact syntax check --
asking if it would be OK to transform an argument into some type
*in the future*.
The result of DATE? (and his many cousins) is simply telling whether
the argument value is *already* of a particular type, because that
argument is *already* transformed from external form into some REBOL
value. In other words,
>> integer? 123
== true
is equivalent to
>> integer! = type? 123
== true
and so on for all XXX?/XXX! pairs, so that
>> integer? "123"
== false
will always be false (no matter what the sequence of characters
supplied) because
>> type? "123"
== string!
As Carl already pointed out, if you're trying to figure out whether
a string *could be* converted to a date (integer, whatever...) in
the obvious way, TRY is your friend (unless you want to write your
own PARSE rules...).
Let me add that if you want to encapsulate that for reuse throughout
your script, you might try one of the following.
looks-like-a-date: func [s [string!]][
not error? try [to-date s]
]
... just tests whether the string *can be* made into a DATE! value.
>> looks-like-a-date "01/13/25" == false
>> looks-like-a-date "01/12/25" == true
On the other hand,
try-date: func [s [string!]][
if error? try [return to-date s] [none]
]
... will return you the converted DATE! value or NONE to signal failure.
>> try-date "01/13/25" == none
>> try-date "01/12/25" == 1-Dec-2025
>> try-date "001/12/25" == 1-Dec-2025
>> try-date "2001/12/25" == 25-Dec-2001
You can use it "as is" in repeated code cliches, such as ...
>> until [birthday: try-date ask "What's your birthday? "]
What's your birthday? 01/13/25
What's your birthday? 01/12/25
== 1-Dec-2025
... or the slightly fancier ...
>> while [
[ none? birthday: try-date ask "What's your birthday? "
[ ][
[ print "^-Please try yyyy-mm-dd format"
[ ] print ["^-Ah," birthday "is a nice date!"]
What's your birthday? 01/13/25
Please try yyyy-mm-dd format
What's your birthday? 25/01/13
Ah, 25-Jan-2013 is a nice date!
Following the DRY principle (Don't Repeat Yourself), you can turn
all of the above into a re-usable function ...
get-a-date: func [
prompt [string!]
/local result
][
while [
none? result: try-date ask prompt
][
print "^-Please try yyyy-mm-dd format"
]
result
]
... which, of course, does this ...
>> get-a-date "What's your birthday? "
What's your birthday? 1/13/25
Please try yyyy-mm-dd format
What's your birthday? 2001/13/25
Please try yyyy-mm-dd format
What's your birthday? 2001/12/25
== 25-Dec-2001
By now I'm sure I've beaten this poor issue to death, but I wanted
to think through the kind of refactoring that I often use to "grow"
reusable ideas/functions in REBOL, which (within certain bounds) is
quite handy for this kind of stream-of-consciousness evolution.
Of course, I apologize if I've insulted your intelligence or
experience! ;-)
Happy REBOLing!
-jn-
--
; sub REBOL {}; sub head ($) {@_[0]}
REBOL []
# despam: func [e] [replace replace/all e ":" "." "#" "@"]
; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"}
print head reverse despam "moc:xedef#yleen:leoj" ;