Issue with Time::Local

S

SSS Develop

Hello,

When i run the following script, I get error:


Day '31' out of range 1..28 at exp.pl line 18



-----------
use strict;
use warnings;
use Time::Local;

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

print timelocal($sec,$min,$hr,$d,$m,$y);
 
H

hymie!

In our last episode, the evil Dr. Lacto had captured our hero,
Hello,

When i run the following script, I get error:


Day '31' out of range 1..28 at exp.pl line 18



-----------
use strict;
use warnings;
use Time::Local;

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;

Global symbol "$string" requires explicit package name at - line 6.
Execution of - aborted due to compilation errors.

--hymie! http://lactose.homelinux.net/~hymie (e-mail address removed)
-------------------------------------------------------------------------------
 
S

SSS Develop

In our last episode, the evil Dr. Lacto had captured our hero,
  SSS Develop <[email protected]>, who said:













Global symbol "$string" requires explicit package name at - line 6.
Execution of - aborted due to compilation errors.

--hymie!    http://lactose.homelinux.net/~hymie   (e-mail address removed)
--------------------------------------------------------------------------- ----


opps... the correct version is as follow:

------------


use strict;
use warnings;
use Time::Local;
my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $date_string;
my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;
print timelocal($sec,$min,$hr,$d,$m,$y);

---------
 
H

hymie!

In our last episode, the evil Dr. Lacto had captured our hero,
Hello,

When i run the following script, I get error:


Day '31' out of range 1..28 at exp.pl line 18
my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

print timelocal($sec,$min,$hr,$d,$m,$y);

what could be issue?

You mean, aside from the obvious problem that February 2011 only has
28 days in it?

--hymie! http://lactose.homelinux.net/~hymie (e-mail address removed)
-------------------------------------------------------------------------------
 
H

hymie!

In our last episode, the evil Dr. Lacto had captured our hero,
(e-mail address removed) (hymie!), who said:
In our last episode, the evil Dr. Lacto had captured our hero,



You mean, aside from the obvious problem that February 2011 only has
28 days in it?

I must have undo'd the last line of my post, which said something like:

Or that you didn't read the documentation, which states
It is worth drawing particular attention to the expected
ranges for the values provided.

--hymie! http://lactose.homelinux.net/~hymie (e-mail address removed)
-------------------------------------------------------------------------------
 
J

Jens Thoms Toerring

SSS Develop said:
When i run the following script, I get error:
Day '31' out of range 1..28 at exp.pl line 18
my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;
-----------------------------------^^^^^^^

Better make that '$date_string'.
my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;
print timelocal($sec,$min,$hr,$d,$m,$y);
-----------------------------------^^

The month value is interpreted as the distance to January,
so you need 0 for January, 1 for February etc. Thus you're
asking here for February 31 - which isn't a valid date.

Regards, Jens
 
T

Tony Mountifield

Hello,

When i run the following script, I get error:


Day '31' out of range 1..28 at exp.pl line 18

-----------
use strict;
use warnings;
use Time::Local;

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

print timelocal($sec,$min,$hr,$d,$m,$y);

This line should be:

print timelocal($sec,$min,$hr,$d,$m-1,$y-1900);

Although I expect it will also accept just $y as the last arg.
It's the $m-1 that is critical.

Cheers
Tony
 
R

Rainer Weikusat

Ben Morrow said:
Quoth (e-mail address removed) (Tony Mountifield):

It's usually a mistake to try to parse date formats yourself. Use
DateTime instead.


Why would this 'usually be a mistake'?
 
J

Jürgen Exner

Rainer Weikusat said:
Why would this 'usually be a mistake'?

Because reusing existing, well-tested code instead of re-inventing the
wheel is a sign of good software development.

jue
 
R

Rainer Weikusat

Jürgen Exner said:
Because reusing existing, well-tested code instead of re-inventing
the wheel is a sign of good software development.

And not using code by someone who believes to have invented something
as important and lasting as 'the wheel' just because he has managed to
split a string using a library routine would be a sign of common
sense: People who overestimate the importance of their work that
grossly quite obviously lack the compentence necessary for a sensible
assessment.

Totschlagargumente benutzt man, weil man sonst keine hat.
 
R

Rainer Weikusat

Ben Morrow said:
Because, as this thread has demonstrated, it's extremely easy to get it
wrong.

Well then, what's wrong with the code in question:

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $date_string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

This splits a complex string into components. I can't see any error in
here.
 
J

Jürgen Exner

Rainer Weikusat said:
Well then, what's wrong with the code in question:

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $date_string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

This splits a complex string into components. I can't see any error in
here.

Nor can anyone else. You are missing the point by several miles.

jue
 
J

Jürgen Exner

Rainer Weikusat said:
And not using code by someone who believes to have invented something
as important and lasting as 'the wheel' just because he has managed to
split a string using a library routine would be a sign of common
sense: People who overestimate the importance of their work that
grossly quite obviously lack the compentence necessary for a sensible
assessment.

Obviously the task wasn't as simple as you are painting it, otherwise
the OP wouldn't have made that error.
On the other hand you are right: if the OP had used the module, then he
would this honorable NG would have missed this great entertainment..
Totschlagargumente benutzt man, weil man sonst keine hat.

"Kein Programm ist nutzlos. Es kann immer noch als schlechtes Beispiel
dienen."
No program is useless. It can always serve as an example for poor
programming.

jue
 
R

Rainer Weikusat

Jürgen Exner said:
Nor can anyone else. You are missing the point by several miles.

The code I requoted above led to a comment 'trying to parse date
formats yourself is usually a mistake'. But no mistake was made when
parsing this date. Instead, the OP made a mistake when calling a
subroutine provided by some module. If error-prone activities are
better avoided (highly debatable since humans learn by making mistakes
and having to correct them), the obvious conclusion would be that
'trying to use existing Perl modules' must be the thing which is
'usually a mistake'. All of this together makes preciously little
sense. Consequently, something must be missing here, namely,
an argument supporting the 'is usually a mistake' assertion.
 
R

Rainer Weikusat

Jürgen Exner said:
Obviously the task wasn't as simple as you are painting it, otherwise
the OP wouldn't have made that error.

The OP tried to use some non-core Perl module and apparently, without
reading the documentation first. That's certainly an error (or at
least bound to cause 'surprises') but not a coding error.
 
J

John W. Krahn

SSS said:
When i run the following script, I get error:

Day '31' out of range 1..28 at exp.pl line 18

perldoc -f localtime

localtime EXPR
localtime
Converts a time as returned by the time function to a
9-element list with the time analyzed for the local time
zone. Typically used as follows:

# 0 1 2 3 4 5 6 7 8
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);

All list elements are numeric, and come straight out of the
C `struct tm'. $sec, $min, and $hour are the seconds,
minutes, and hours of the specified time.

$mday is the day of the month, and $mon is the month
itself, in the range 0..11 with 0 indicating January and 11
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
indicating December. This makes it easy to get a month
^^^^^^^^^^^^^^^^^^^
name from a list:

my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct
Nov Dec );
print "$abbr[$mon] $mday";
# $mon=9, $mday=18 gives "Oct 18"

$year is the number of years since 1900, not just the last
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
two digits of the year. That is, $year is 123 in year
2023. The proper way to get a complete 4-digit year is
simply:

$year += 1900;

Otherwise you create non-Y2K-compliant programs--and you
wouldn't want to do that, would you?

use strict;
use warnings;
use Time::Local;

my $date_string = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;

my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;

print timelocal($sec,$min,$hr,$d,$m,$y);

my ( $y, $m, $d, $hr, $min, $sec ) = $date_string =~ /\d+/g

print timelocal( $sec, $min, $hr, $d, $m - 1, $y - 1900 );



John
 
S

SSS Develop

SSS said:
When i run the following script, I get error:
Day '31' out of range 1..28 at exp.pl line 18

perldoc -f localtime

     localtime EXPR
     localtime
             Converts a time as returned by the time function to a
             9-element list with the time analyzed for the local time
             zone.  Typically used as follows:

                 #  0    1    2     3    4    5     6     7     8
                 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
                                                         localtime(time);

             All list elements are numeric, and come straight out of the
             C `struct tm'.  $sec, $min, and $hour are the seconds,
             minutes, and hours of the specified time.

             $mday is the day of the month, and $mon is themonth
             itself, in the range 0..11 with 0 indicating January and 11
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             indicating December.  This makes it easy to get a month
             ^^^^^^^^^^^^^^^^^^^
             name from a list:

                 my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct
Nov Dec );
                 print "$abbr[$mon] $mday";
                 # $mon=9, $mday=18 gives "Oct 18"

             $year is the number of years since 1900, not just the last
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             two digits of the year.  That is, $year is 123 in year
             2023.  The proper way to get a complete 4-digit year is
             simply:

                 $year += 1900;

             Otherwise you create non-Y2K-compliant programs--and you
             wouldn't want to do that, would you?
use strict;
use warnings;
use Time::Local;
my $date_string  = '2011-01-31 17:30:55';
my ($date, $time) = split /\s+/, $string;
my ($y, $m, $d) = split /-/, $date;
my ($hr, $min, $sec) = split /:/, $time;
print timelocal($sec,$min,$hr,$d,$m,$y);

my ( $y, $m, $d, $hr, $min, $sec ) = $date_string =~ /\d+/g

print timelocal( $sec, $min, $hr, $d, $m - 1, $y - 1900 );

John
--
Any intelligent fool can make things bigger and
more complex... It takes a touch of genius -
and a lot of courage to move in the opposite
direction.                   -- Albert Einstein

Thank you,

this works ! was stupid mistake of not going through the details of
documentation :(


---sssdevelop
 
J

Justin C

The code I requoted above led to a comment 'trying to parse date
formats yourself is usually a mistake'. But no mistake was made when
parsing this date. Instead...

<Yawn>

From: (e-mail address removed)
Score: -1000


Justin.
 
R

Rainer Weikusat

Justin C said:
<Yawn>

From: (e-mail address removed)
Score: -1000

I usually score people down by -9999 because I really don't want to
read nonsense texts from people who are much more interested in
farting loudly in public than discuss language or programming issues.

HTH.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top