Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Not able to ParseDate lines from a file

by xpl0it (Initiate)
on Feb 03, 2012 at 07:20 UTC ( [id://951614]=perlquestion: print w/replies, xml ) Need Help??

xpl0it has asked for the wisdom of the Perl Monks concerning the following question:

Guys, I am a beginner in Perl, and I have a small query. I have written a script which selects a line from a file and extracts the date part of it. This date, I want to Parse (in anyway) to obtain the Epoch time. The error which I get and the code which I have written is as follows. I have tried a number of ways to parse the date. If I give ParseDate(""), it works, but if I give the line which I read from the file, it does not work. Please help. Error which I get:
The 'year' parameter (undef) to DateTime::new was an 'undef', which is + not one of the allowed types: scalar at /usr/local/lib/perl/5.10.1/DateTime.pm line 200 DateTime::new(undef, 'year', undef, 'month', 1, 'day', 1, 'hour', +1, ...) called at smsDone line 60
The Code which I have written
$file_name = "sms.vmg"; tie my @array, 'Tie::File', $file_name or die("Unable to open file \"$ +file_name\": $!\n"); my $year = substr $array[13], 22, 8; my $month = substr $array[13], 16, 2; my $date = substr $array[13], 10, 4; my $hour = substr $array[13], 32, 4; my $minutes = substr $array[13], 38, 4; my $seconds = substr $array[13], 44, 4; $dt = DateTime->new( year=>$year, month=>$month, day=>$date, hour=>$hour, minute=>$minutes, second=>$seconds, nanosecond=>0, time_zone => 'Asia/Calcutta'); $epoch_time = $dt->epoch * 1000; print "\nEpoch Time: ".$epoch_time;
Update: I missed adding ... the date is in the format "dd.mm.yyyy hh:mm:ss". For example "21.06.2010 07:06:11"

Replies are listed 'Best First'.
Re: Not able to ParseDate lines from a file
by ikegami (Patriarch) on Feb 03, 2012 at 07:26 UTC

    The error message complains about the value for year, to which you pass $time, to which you never assign a value.

    Please, always use use strict; use warnings;.

      The code which I had uploaded was not right. That was a code which I was testing. I have made the changes. Kindly advice. Thanks

        xpl0it:

        Well you still need to check what you're passing in. The error message is quite clearly stating that you're not passing in a valid value for year, so either run your script in debug mode or add some print statements to display values of various variables so you can see what's going on. (For simple quick & dirty stuff, I generally add a print or two, but for tougher problems, I use debug mode.)

        You really ought to familiarize yourself with the debugger, so I suggest trying it out. Run your script like perl -d scriptname.pl and read up on perldebug and have some fun.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: Not able to ParseDate lines from a file
by tobyink (Canon) on Feb 03, 2012 at 13:36 UTC

    VMG is Nokia's format for storing SMS messages in. It is UCS-2 LE encoded. If you stop using Tie::File, and just open and readline the file like a normal person, then you can use Perl's IO layer to decode the UCS-2 LE encoding.

    Supply an actual sample file and you might get more useful and complete answers.

Re: Not able to ParseDate lines from a file
by xpl0it (Initiate) on Feb 03, 2012 at 12:27 UTC

    Ok. Maybe I wasnt able to explain the problem. Here it is point by point. I want a particular line from a file, which has the format "Date: DD:MM:YYYY HH:MM:SS", parse it to identify the date part and find the epoch time. Here is what I am trying to do: Lets take the example of the line as "Date: 02.07.2011 16:14:48"

    * I read the full date from the file (including the "Date:" which is included in the line) and put it in a scalar variable $array

    * Once I get the date in $array, I read the individual numbers. For example, to get the Year, I use the substr function to find the exact start of the year, till the exact end. Here, 22 is the starting point of the year and reading 8 units to read the entire Year. Strangely, it is calculating 8 units for 4 digits.

    * I do the same for the others, reading the Month, the day, the Hours, Minutes and Seconds using the substr function. When I print these values, I get the correct output. For $year, I get the 4 digit year, for example 2011. For $month, I get the two digit month value, 07. For $date, I get the two digits, and so on for all others.

    * These values are passed on to the DateTime->new function to get the epoch time. This generates an error saying I have entered an undefined value!

    I have tried playing around with the scalars, and I am not able to identify where I am wrong.

    Corion, I had to put  $year=substr $array[13],22,8 since that is what is giving me the full year (2011).

    I even used the Function ParseDate(). When I directly give the ParseDate() a string, like this  ParseDate("02.07.2011 16:14:48");, things work great, but when try the script $time=substr $array[13],22,8; ParseDate($time); I get an error saying the input is undef.

    Jethro, when I executed your code using the Dumper, I got the following output: $VAR1 = "\0002\0000\0001\0000"; Would really appreciate if you could explain.

    Thanks guys for the help. I hope I have been able to explain my problem. Looking forward to some more help. Thanks

      Your prose description of what you think your code does sounds nice. But it does not relate at all to what your program is doing, otherwise your program would be working.

      Reduce your program to a small, self-contained example. Also post the input data. Maybe your input data is nothing at all like what you expect. The Data::Dumper output seems to confirm that. The unusual length of 8 bytes for what should be a 4-byte number confirms that. So investigate, reduce and debug your program and thus your problem.

      DateTime::Format::Natural can parse the string for you. You don't have to reinvent the wheel. Try this:
      #!/usr/bin/perl -l use strict; use warnings; use DateTime; use DateTime::Format::Natural; my $parser = DateTime::Format::Natural->new; my $extract_string = "Date: 02.07.2011 16:14:48"; my $date_string = $parser->extract_datetime($extract_string); my $dt = $parser->parse_datetime($date_string); my $epoch_time = $dt->epoch; print $epoch_time;

      The other answers should help you already with your problem, but if you are interested in the mystery of your $year number, read on.

      If you want to specify control characters or some other non-printable character codes in perl you can use special codes. For example to put a newline into strings you could use \n or hexadecimal \x0a or octal \013. What you see in your Dumper output is a zero byte, \000 aka \x00, followed by \x32 which is (in ASCII or UTF-8) a "2" character followed by \x00 again.... It seems to be a 16-bit character format. Printing this will look like "2010" because \x00 doesn't have a character icon, but for perl it is not a string it can convert to numbers.

Re: Not able to ParseDate lines from a file
by ikegami (Patriarch) on Feb 12, 2012 at 04:29 UTC

    According to your updated code and the associated message,

    substr $array[13], 22, 8

    returns undef while

    substr $array[13], 32, 4

    returns 1. I don't believe that is possible. I believe the information you gave us is (still) incorrect.

    By the way, I'd use:

    use DateTime::Format::Strptime qw( ); my $format = DateTime::Format::Strptime->new( pattern => '%d.%m.%Y %H:%M:%S', time_zone => 'Asia/Calcutta', on_error => 'croak', ); my $dt = $Strp->parse_datetime($array[13]);

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://951614]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-24 17:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found