General Purpose Date Script

UNIX for Beginners Questions & Answers




Kindly Note - This is a Single User Post by Forum Member Corona688 Regarding:
General Purpose Date Script.
Please Follow The Primary Link Above to View the Full Discussion.

   
Old 10-28-2013
Corona688 Corona688 is offline Forum Staff  
Mead Rotor
 
Join Date: Aug 2005
Last Activity: 20 July 2018, 3:26 PM EDT
Location: Saskatchewan
Posts: 22,727
Thanks: 1,194
Thanked 4,351 Times in 4,006 Posts
I get no such errors here, even when fiddling with the TZ variable (which perl appears to support). What version of perl do you use?

The real error was that the string 'now', which caused no errors, wasn't supported and should have been flagged.

Error detection has been made more robust as a result and support for 'now' added:

Code:
#!/usr/bin/perl

use POSIX;

my $cmdstr="%Y-%m-%d %H:%M:%S";
my ($input, $arg, $sign)=(undef, undef, 0);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();

# Commandline parsing stuff
while(defined($arg=shift)) {
        if($arg =~ /^--date=/)  {       $input=substr($arg, 7);         }
        elsif($arg =~ /^-d$/)   {       $input=shift;                   }
        elsif($arg =~/^\+/)     {       $cmdstr=substr($arg,1);         }
        else                    {       print STDERR "unknown $arg\n";  }
}

# Put the date string back into argv, split on spaces
unshift(@ARGV, split(/[ \t]+/, $input));

while(defined($arg=shift))
{
        # Need to split +1 into +1
        if($arg =~ /^[+]/) {    $sign=1;        $arg=substr($arg,1);    }
        elsif($arg =~ /^-/) {   $sign=-1;       $arg=substr($arg,1);    }

        ################## DATE FORMAT DETECTION ########################

        # @1234 means seconds in epoch time
        if($arg =~ /^@[0-9]+$/)
        {
                ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($1+0);
                next;
        }

        # Checks for YYYYMMDD or YYYY/MM/DD time
        # TODO:  Check for YYMMDD dates
        # TODO:  Check for YYYYDDMM dates (ugh)
        if($arg =~ /^([0-9]{4})(\/?)([0-9]{2})\2([0-9]{2})/)
        {
                ($year,$mon,$mday)=($1-1900,$3-1,$4+0);
                ($sec,$min,$hour)=(0,0,0);
                next;
        }

        # HH:MM:SS times
        if($arg =~ /([0-2][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?$/)
        {
                ($sec,$min,$hour)=($3+0, $2+0, $1+0);
                next;
        }

        # As last resort, assume its a pure number.
        if($arg =~ /^([0-9]+)$/) {
                if($sign == 0)
                {
                        print STDERR "offset without unit";
                        exit(1);
                }

                $offset=$1+0;
                next;
        }

        if($arg =~ /^seconds?$/)        {       }
        elsif ($arg =~ /^years?$/) {
                                        $year += ($offset*$sign);
                                        $sign=0;
                                        $offset=0;
                                }
        elsif($arg =~ /^minutes?$/)     {       $offset *= 60;          }
        elsif($arg =~ /^hours?/)        {       $offset *= 60*60;       }
        elsif($arg =~ /^days?/)         {       $offset *= 60*60*24;    }
        elsif($arg =~ /^weeks?/)        {       $offset *= 60*60*24*7;  }
        elsif($arg =~ /^months?$/)      {

                                        $mon += ($offset*$sign);

                                        while($mon > 12)
                                        {
                                                $mon-=12;
                                                $year++;
                                        }

                                        while($mon < 0)
                                        {
                                                $mon+=12;
                                                $year--;
                                        }

                                        $sign=0;
                                        $offset=0;
                                }
        elsif($arg =~ /^now$/)  {
                ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();
        }
        elsif(length($arg) == 0){       } # Empty string?  Ignore
        else                    {
                                        print STDERR "Unknown argument $arg\n";
                                        exit(1);
        }
}

# Convert the altered year, month, etc back into epoch time.
my $ref=mktime($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
# Add the seconds offset calculated above.
$ref += ($sign * $offset);
# Convert back into list.
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($ref);

print strftime($cmdstr."\n",
        $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);


Last edited by Corona688; 10-28-2013 at 12:16 PM..