开发者

How to find days difference between the current day and input date

开发者 https://www.devze.com 2023-04-08 11:58 出处:网络
$a = \"Sat Aug 04 23:59:59 GMT 2012\" How to find t开发者_开发知识库hat is that $a is 100 days older ?
$a = "Sat Aug 04 23:59:59 GMT 2012"

How to find t开发者_开发知识库hat is that $a is 100 days older ?

I can't use any extra perl modules because i cant install it on all hosts


You should use DateTime if available, but if not, then the below should do. Really, at this stage, you should rolling your own date logic, but it still is pretty easy using core module POSIX.

use strict;
use warnings;
use POSIX ();

# get a list of month symbols
my @mons = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;

# Create a symbol -> number table
my %num_for 
    = do {
        my $mon = 0;
        map { $_ => $mon++ } @mons;
    };

# Create the alternation of months

# Create line regex
my $time_rex 
    = qr/ (${\join( '|', @mons )}) 
          \s+ 
          0? (\d+) 
          \s+ 
          (\d{2}) : (\d{2}) : (\d{2}) 
          \s+ 
           # I made the tz optional to handle scalar( localtime )
          (?: (\p{alpha}+) \s+ )?
          (\d{4})
        /x
     ;
...

# Convienience function
sub get_time_value {
    # parse date string
    return unless my @fields = ( shift =~ /$time_rex/ );
    # get numerical month
    $fields[0]  = $num_for{ $fields[0] };
    # perl year kludge
    $fields[-1] -= 1900;
    return wantarray ? @fields[ 4, 3, 2, 1, 0, 6, 5 ]
         :             POSIX::mktime( @fields[ 4, 3, 2, 1, 0, 6 ] )
         ;
}

sub days_prior_to_now {
    return unless defined( my $days_prior = shift );
    return time unless $days_prior;

    $days_prior = - $days_prior if $days_prior < 0;
    my $date_string =  scalar( localtime );
    return unless my ( $sec, $min, $hr, $day, $mon, $year, $tz ) 
           = get_time_value( $date_string )
           ;
    return POSIX::mktime( $sec, $min, $hr, $day - $days_prior, $mon, $year );
}

sub is_100_days_before_now {
    my $a_string    = shift;

    croak "Could not parse '$a_string'!" 
        unless my $a_value = get_time_value( $a_string );
    return $a_value < days_prior_to_now( 100 );
}

if ( is_100_days_before_now( $a )) { 
    ...
}


First you have to parse that string in a DateTime object, using DateTime::Format::Builder, to build a custom string parser. Then you can get the difference between the two with:

$dt->delta_days( $datetime );

Where $dt is the DateTime object from string parse, and $datetime is your reference ( another DateTime object ).


If you get over your fear of modules, Date::Calc would make short work of this:

$ perl -MDate::Calc=Delta_Days,Parse_Date,Today -E 'say Delta_Days(Today, Parse_Date(shift))' "Sat Aug 04 23:59:59 GMT 2012"
312


There are a lot of date time modules available in the standard Perl installation which means there's no need to install anything. This module has been available in some form since version Perl 3.x:

  • Time::Local

Here are others in version 5.8:

  • Time::tm
  • Time::gmtime
  • Time::localtime

Newer versions of Perl include:

  • Time::Piece

You can use the perldoc command to see which modules you have installed:

C:> perldoc -l Time::Piece
C:\Perl\lib\Time\Piece.pm

Unix stores time in the number of seconds since "The Epoc" which is January 1, 1970, and Perl does the same thing (even on Windows).

Thus, once you translate your date into a Perl time, you can simply subtract 8,640,000 which is the number of seconds in a 100 days. (100 days * 24 Hours/day * 60 minutes/hour * 60 seconds/minute), then convert this back into a string.

At a very, very basic level, you can do this using the gmtime function in Perl and the timegm in the Local::Time module.

Other modules make it very simple to convert time from format to another and even do some math. My favorite is Time::Piece which allows you to use strptime format to quickly convert your time from whatever format it happens to be in. Then you can use the epoc member function to convert the time back into seconds, subtract 8,640,000, and reconvert it back into a string.


If Time::Piece is core in your version of perl:

use strict;
use warnings;

use Time::Piece;
use Time::Seconds qw(ONE_DAY);

my $t = "Sat Aug 04 23:59:59 GMT 2012";
my $dt = Time::Piece->strptime($t, "%a %b %d %T %Z %Y");

my $day_str = $dt->strftime("%F");
my $day = Time::Piece->strptime($day_str, "%Y-%m-%d") + 100.5*ONE_DAY();

print $day->strftime("%F"),"\n";
0

精彩评论

暂无评论...
验证码 换一张
取 消