Forum: Ruby Why does 'Date::strptime' accept invalid strings as valid month names ?

249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-06-09 17:36
(Received via mailing list)
Hi,

I was looking for if I can use *Date::strptime* method to check if a
string
can be validate as *valid* month or not, Thus I tested it with few
random
strings. It was meeting my expectation too.


Date::strptime("January",'%B')
# => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
 Date::strptime("JaNuary",'%B')
# => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
Date::strptime("JaNua",'%B')
#  => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
2.0.0-p451 :005 > Date::strptime("Foo",'%B')
# ArgumentError: invalid date
Date::strptime("Jan",'%B')
# => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
Date::strptime("Janu",'%B')
# => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>

Now all are going above my head.

Date::strptime("Marche",'%B')
# => #<Date: 2014-03-01 ((2456718j,0s,0n),+0s,2299161j)>
Date::strptime("Marcheee",'%B')
#=> #<Date: 2014-03-01 ((2456718j,0s,0n),+0s,2299161j)>
Date::strptime("Mayil",'%B')
# => #<Date: 2014-05-01 ((2456779j,0s,0n),+0s,2299161j)>
Date::strptime("Juneixyt",'%B')
# => #<Date: 2014-06-01 ((2456810j,0s,0n),+0s,2299161j)>

Does that mean valid English month name checking this way is not safe ?
:(


--
================
Regards,
Arup Rakshit
================
Debugging is twice as hard as writing the code in the first place.
Therefore,
if you write the code as cleverly as possible, you are, by definition,
not
smart enough to debug it.

--Brian Kernighan
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2014-06-09 17:56
(Received via mailing list)
On Mon, Jun 9, 2014 at 4:35 PM, Arup Rakshit
<aruprakshit@rocketmail.com> wrote:
> # => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
>
> Date::strptime("Marche",'%B')
> # => #<Date: 2014-03-01 ((2456718j,0s,0n),+0s,2299161j)>
> Date::strptime("Marcheee",'%B')
> #=> #<Date: 2014-03-01 ((2456718j,0s,0n),+0s,2299161j)>
> Date::strptime("Mayil",'%B')
> # => #<Date: 2014-05-01 ((2456779j,0s,0n),+0s,2299161j)>
> Date::strptime("Juneixyt",'%B')
> # => #<Date: 2014-06-01 ((2456810j,0s,0n),+0s,2299161j)>
>
> Does that mean valid English month name checking this way is not safe ? :(

It looks like MRI is checking the words only up to the month's name
length (check:
https://github.com/ruby/ruby/blob/a3a6da5ec51c1739...)



     case 'B':
     case 'b':
     case 'h':
{
   int i;

   for (i = 0; i < (int)sizeof_array(month_names); i++) {
size_t l = strlen(month_names[i]);
if (strncasecmp(month_names[i], &str[si], l) == 0) {
   si += l;
   set_hash("mon", INT2FIX((i % 12) + 1));
   goto matched;
}
   }
   fail();
}

So, if your string contains the name of the month, it will match, even
though it contains further characters.

Jesus.
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-06-09 18:20
(Received via mailing list)
On Monday, June 09, 2014 05:56:14 PM Jess Gabriel y Galn wrote:
>
> So, if your string contains the name of the month, it will match, even
> though it contains further characters.
>
> Jesus.

Some more exception. How the below are valid also, as junks between the
actual
names also not making Ruby to throw error as *Invalid date*, as it
supposed to
do:

2.0.0-p451 :003 >  Date::strptime("Jantuary",'%B')
 => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
2.0.0-p451 :004 >  Date::strptime("Janxtuary",'%B')
 => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
2.0.0-p451 :005 >


--
================
Regards,
Arup Rakshit
================
Debugging is twice as hard as writing the code in the first place.
Therefore,
if you write the code as cleverly as possible, you are, by definition,
not
smart enough to debug it.

--Brian Kernighan
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2014-06-09 18:24
(Received via mailing list)
On Mon, Jun 9, 2014 at 5:20 PM, Arup Rakshit
<aruprakshit@rocketmail.com> wrote:
>
> 2.0.0-p451 :003 >  Date::strptime("Jantuary",'%B')
>  => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
> 2.0.0-p451 :004 >  Date::strptime("Janxtuary",'%B')
>  => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
> 2.0.0-p451 :005 >

You can see in the link I pasted before, that it's trying to match the
following names:

static const char *month_names[] = {
    "January", "February", "March", "April",
    "May", "June", "July", "August", "September",
    "October", "November", "December",
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

So, even though January doesn't match, Jan does, and so it is parsed.

Jesus.
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-06-10 22:06
(Received via mailing list)
On Monday, June 09, 2014 06:23:56 PM Jess Gabriel y Galn wrote:

>
> So, even though January doesn't match, Jan does, and so it is parsed.
>
> Jesus.

Another thing to note here for Time objects. I used *Time#strftim* by
mistake
with *%Q* option and got the below output, which forced me to check the
doc
and I found it is not there. I expected some error,while invalid *string
formats*. But it gave me the *string* back.

time = Time.now
time.strftime("%Q") # => "%Q"

--
================
Regards,
Arup Rakshit
================
Debugging is twice as hard as writing the code in the first place.
Therefore,
if you write the code as cleverly as possible, you are, by definition,
not
smart enough to debug it.

--Brian Kernighan
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-11 01:11
(Received via mailing list)
On Jun 10, 2014, at 12:05, Arup Rakshit <aruprakshit@rocketmail.com>
wrote:

> formats*. But it gave me the *string* back.
From the doco:

> The directives begin with a percent (%) character. Any text not listed as a
> directive will be passed through to the output string.

I interpret that to mean that "%<anything-not-actually-a-directive>"
will pass through just like your example:
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-06-11 06:23
(Received via mailing list)
On Tuesday, June 10, 2014 04:10:49 PM Ryan Davis wrote:

> From the doco:
> > The directives begin with a percent (%) character. Any text not listed as
> > a
> > directive will be passed through to the output string.
>
> I interpret that to mean that "%<anything-not-actually-a-directive>" will
pass through just like your example:

Thank Ryan. Yes it is mentioned in the doc, and somehow I skipped that
while I
was reading the doc.

--
================
Regards,
Arup Rakshit
================
Debugging is twice as hard as writing the code in the first place.
Therefore,
if you write the code as cleverly as possible, you are, by definition,
not
smart enough to debug it.

--Brian Kernighan
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.