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

I have 2 sub
sub get_date { # -------------------------------------------------------- # Returns the date in the format "Mmmm dd, yyyy hh:mm ". # Warning: If you change the default format, you must also modif +y the &date_to_unix # subroutine below which converts your date format into a unix t +ime in seconds for sorting # purposes. my ($time) = @_; ($time) || ($time = time()); my ($sec, $min, $hour, $day, $mon, $year, $dweek, $dyear, $day +light) = localtime($time); ($day < 10) and ($day = "0$day"); $mon += 1; ($mon < 10) and ($mon = "0$mon"); $year = $year + 1900; if ($min < 10) { $min = "0" . $min; } return "$mon\/$day\/$year $hour:$min:$sec"; } sub date_to_unix { my ($date) = @_[0]; my ($time); my ($mon, $day, $year) = split(/\//, $_[0]); my ($hour, $min, $sec) = split(/:/, $_[0]); unless ($day and $mon and $year) { return undef; } use Time::Local; eval { $mon = int($mon) - 1; $ +day = int($day); $year = int($year) - 1900; $time = timelocal($sec,$mi +n,$hours,$day,$mon,$year); }; if ($@) { return undef; } # + Could return 0 if you want. return ($time); }
I am using flat file database:
SN|Startdate|Completedate|Status
1234ABC|09/23/2003 14:30|09/30/2003 10:00|Completed
If I want to check for the running time I should change starttime and complete time to epoch and tell me days, hrs, min but why when I use sub datetounix it only count how many day like 09/30 - 09/23 = 7 days Could you help me to fix my sub datetounix. Thanks

Edit by thelenm: put <code> tags around code

Replies are listed 'Best First'.
Re: date time to unix
by Aristotle (Chancellor) on Oct 01, 2003 at 18:36 UTC
    If all you need this for is sorting purposes, then it suffices to swap the figures in the date, and it will sort correctly, ie something like
    my ($date, $time) = split / /, $datetime; $date = join '/', reverse split m[/], $date; $datetime = "$date $time";

    Now the dates from your example data will look like 2003/09/23 14:30 and 2003/09/30 10:00 which is in correct sorting order.

    For the record, though, the culprit is you're forgetting to split up your string between date and time. So the time portion ends up trailing the year when you split the date, and the date ends up in front of the hour when split the time.

    If you put a few print statements in, you'll notice the problem right away:

    my ($mon, $day, $year) = split(/\//, $_[0]); my ($hour, $min, $sec) = split(/:/, $_[0]); print "$mon - $day - $year\n"; print "$hour - $min - $sec\n";
    The solution is half there in your code already. I wonder why you assign the first parameter to $date at the beginning of your function, then never use it? If you change this bit:
    my ($date) = @_; my ($time);
    to read like
    my ($datetime) = @_; my ($date, $time) = split / /, $datetime;
    the rest of your code should work as is.

    Makeshifts last the longest.

    Edited by castaway: added some [, ] as appropriate
Re: date time to unix
by Nkuvu (Priest) on Oct 01, 2003 at 18:29 UTC

    Wow. Your indenting is all over the place. Not to mention that the comment on the get_date sub is inaccurate and therefore misleading. But minor quibbles aside, I'd suggest using <code> tags to enclose code blocks. Your code looks odd because of things that appear to be $_0 which isn't valid. It looks like you meant $_[0], though. Oh, and @_[0] should probably be $_[0] anyway.

    Anyway, that's all extraneous info. I ran your script snipppet through perl with the -wc switch. There was a warning about $hours in the date_to_unix sub. Your split is also not working properly.

    I added the line die "Mon: $mon\nDay: $day\nYear: $year\nHour: $hour\nMin: $min\nSec: $sec\n"; after the split and got the following output when calling date_to_unix with the string "09/23/2003 14:30":

    Mon: 09 Day: 23 Year: 2003 14:30 Hour: 09/23/2003 14 Min: 30 Sec:

    So there's some direction, but no discrete answers. I leave it as an exercise to the reader to fill in the holes.

    Update: The comment about using code tags has been taken care of. So that part of my note is obviously not relevant any more. :)

Re: date time to unix
by Roger (Parson) on Oct 02, 2003 at 07:46 UTC
    Your code for date_to_unix failed because your split statement didn't produce expected results. I am not sure why you use eval, but anyway, I have quickly wrote my version of the date_to_unix and get_date which would do the same thing.
    use strict; use Time::Local; my $date = "09/23/2003 14:30"; printf "%s\n", &date_to_unix($date); printf "%s\n", &get_date(&date_to_unix($date)); exit(0); sub date_to_unix() { my ($mon,$day,$year,$hour,$min) = $_[0] =~ /(\d+)\/(\d+)\/(\d+)\s(\d+):(\d+)/; return undef unless ($day and $mon and $year); return timelocal(0,$min,$hour,$day,$mon-1,$year-1900); } sub get_date() { my $time = shift || time(); my ($sec, $min, $hour, $day, $mon, $year) = localtime($time); # use sprintf to do string formatting for you in one go. # %02d will print digit preceeded with 0 if less than 10 and so on +... return sprintf "%02d/%02d/%04d %02d:%02d", $mon+1, $day, $year+1900, $hour, $min; }