简体   繁体   中英

How do I find a date which is three days earlier than a given date in Perl?

如何找到比Perl中给定日期提前3天的日期,格式为YYYY-MM-DD?

Date::Calc is the champion module here:

use strict;
use warnings;
use Date::Calc qw(Add_Delta_YMD);

my $startDate = '2000-01-01';
my ($startYear, $startMonth, $startDay) = $startDate =~ m/(\d{4}-(\d{2})-\d{2})/;

# 1 year, 2 months, 3 days, after startDate
my $endDate = join('-', Add_Delta_YMD($startYear, $startMonth, $startDay, 1, 2, 3));

The module has a huge number of time conversion routines, particularly those dealing with deltas. DateTime and Date::Manip are also worth checking out.

Date::Calc can be used for such calculations:

#!/usr/bin/perl

use strict;
use warnings;
use Date::Calc qw(Add_Delta_Days);

my ( $yyyy, $mm, $dd ) = ( 2009, 9, 2 );
my @date = Add_Delta_Days( $yyyy, $mm, $dd, -3 );
print join( '-', @date );

DateTime is the canonical way for dealing with dates in modern Perl:

use DateTime;

my ($year, $month, $day) = split '-', '2009-09-01';

my $date = DateTime->new( year => $year, month => $month, day => $day );

$date->subtract( days => 3 );

# $date is now three days earlier (2009-08-29T00:00:00)

There are so many options that it is moderately embarrassing. It depends in part on what other calculations you might need in the future, and whether times and time zones will ever be a factor, and similar things.

You could look at any of these

to name but three (sets of) modules. I'd suggest Date::Calc or Date::Manip for simplicity - but if you're going to need to get fancy in future, the DateTime modules may be better.

See perldoc POSIX for the function mktime() .

It will help you convert dates and times to a simple number, which is the Unix time (the number of seconds since January 1, 1970, I believe). Then, just subtract 3 (days) times 24 (hours in a day) times 60 (minutes in an hour) times 60 (seconds in a minute), or 259200 seconds from that number, and use localtime() to convert that number of seconds back to a string representation.

This is probably the best solution*, because it will handle month and year changes automatically. Any other solution will probably end up being more complicated after factoring in checking to see if we ran out of days in a month, or ran out of months in a year.


EDIT: *Outside of looking on CPAN .

The neat thing about mktime is that it will handle any time of offset. It uses January=0; and Year 2009 = 109 in this scheme. Thus, printed month - 1 and full year - 1900.

use POSIX qw<mktime>;

my ( $year, $month, $day ) = split '-', $date;
my $three_day_prior = mktime( 0, 0, 0, $day - 3, $month - 1, $year - 1900 );

mktime is useful for finding the last day of the month as well. You just go to day 0 of the next month.

mktime( 0, 0, 0, 0, $month, $year - 1900 );

This is simple with Date::Simple

C:\>perl -MDate::Simple=today -e "print today()-3"
2009-08-30

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM