--------------------------------------------------------------------
4.17: How do I find yesterday's date?
(contributed by brian d foy)
Use one of the Date modules. The "DateTime" module makes it simple, and
give you the same time of day, only the day before.
use DateTime;
my $yesterday = DateTime->now->subtract( days => 1 );
print "Yesterday was $yesterday\n";
You can also use the "Date::Calc" module using its "Today_and_Now"
function.
use Date::Calc qw( Today_and_Now Add_Delta_DHMS );
my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
print "@date_time\n";
Most people try to use the time rather than the calendar to figure out
dates, but that assumes that days are twenty-four hours each. For most
people, there are two days a year when they aren't: the switch to and
from summer time throws this off. Let the modules do the work.
--------------------------------------------------------------------
The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
are not necessarily experts in every domain where Perl might show up,
so please include as much information as possible and relevant in any
corrections. The perlfaq-workers also don't have access to every
operating system or platform, so please include relevant details for
corrections to examples that do not work on particular platforms.
Working code is greatly appreciated.
If you'd like to help maintain the perlfaq, see the details in
perlfaq.pod.
So according to the last part, that makes
time - 86400
unreliable?
E.G.,
$ perl -e 'print scalar localtime(time - 86400), "\n";'
Or is it safe to use that?
--
szr
Yes.
> E.G.,
> $ perl -e 'print scalar localtime(time - 86400), "\n";'
Consider:
% perl -le 'print scalar localtime(1206914460)'
Mon Mar 31 00:01:00 2008
% perl -le 'print scalar localtime(1206914460-86400)'
Sat Mar 29 23:01:00 2008
% perl -le 'print scalar localtime(1225061940)'
Sun Oct 26 23:59:00 2008
% perl -le 'print scalar localtime(1225061940-86400)'
Sun Oct 26 00:59:00 2008
> Or is it safe to use that?
Only after 01:00 and before 23:00.
hp
> > Most people try to use the time rather than the calendar to figure
> > out dates, but that assumes that days are twenty-four hours each.
> > For most people, there are two days a year when they aren't: the
> > switch to and from summer time throws this off. Let the modules do
> > the work.
>
> So according to the last part, that makes
> time - 86400
> unreliable?
>
> E.G.,
> $ perl -e 'print scalar localtime(time - 86400), "\n";'
>
> Or is it safe to use that?
Well, that last paragraph explains why that won't work. There are two
days where it breaks. On one you'll get the date from two days ago, and
the other the same day. So, no, it's not safe.
I'm still not sure, from what you guys have discovered,
what the faq *should* say?
Eg suggested explanations for a boss who complains
about how it works on those two days or not within a certain
part of the day?
I wonder how the finance and legal worlds handle this
stuff, eg in a contract?
David
The FAQ should say what it actually says (well, it could also mention
localtime/mktime - I'm not sure if the two modules it mentions are part
of the core).
> Eg suggested explanations for a boss who complains
> about how it works on those two days or not within a certain
> part of the day?
It works correctly if you follow the advice in the FAQ. If you do what
the FAQ says you shouldn't do, it may work in Arizona (Andrew is lucky
not having to put up with that DST insanity) but not in many other
parts of the world.
> I wonder how the finance and legal worlds handle this
> stuff, eg in a contract?
Mostly by ignoring it, I guess. The time shift occurs in the wee hours
of sunday morning. The finance and legal worlds don't do much at that
time.
hp
They are not part of the core.
The core module Time::Local + localtime() are sufficient to answer the
FAQ question safely.
use Time::Local;
my $today = timelocal 0, 0, 12, ( localtime )[3..5];
my ($d, $m, $y) = ( localtime $today-86400 )[3..5];
printf "Yesterday: %d-%02d-%02d\n", $y+1900, $m+1, $d;
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
Doesn't Peter's post contradict this, since his example demonstrated
that the -86400 can lead to a result that is 2 days older?
No. Can't you spot a difference between the above code and
print scalar localtime(time-86400);
??
oh, that was your whole point. sorry :-).
or - as I wrote - localtime and mktime (in POSIX). mktime lets you do
arithmetic on the day field, so you can directly write "the day before"
instead of "the day that was 86400 seconds before noon of the current
day" as you did above.
#!/usr/bin/perl
use warnings;
use strict;
use POSIX qw(mktime strftime);
before_and_after(time);
before_and_after(1206914460);
before_and_after(1225061940);
sub before_and_after {
my ($now) = @_;
print strftime("%Y-%m-%d %H:%M:%S%z\n", localtime($now));
my @today = localtime($now);
my @yesterday = @today; $yesterday[3]--; $yesterday[8] = -1;
my $yesterday = mktime(@yesterday);
print strftime("%Y-%m-%d %H:%M:%S%z\n", localtime($yesterday));
my @tomorrow = @today; $tomorrow[3]++; $tomorrow[8] = -1;
my $tomorrow = mktime(@tomorrow);
print strftime("%Y-%m-%d %H:%M:%S%z\n", localtime($tomorrow));
print "\n";
}
__END__
2008-05-31 11:24:30+0200
2008-05-30 11:24:30+0200
2008-06-01 11:24:30+0200
2008-03-31 00:01:00+0200
2008-03-30 00:01:00+0100
2008-04-01 00:01:00+0200
2008-10-26 23:59:00+0100
2008-10-25 23:59:00+0200
2008-10-27 23:59:00+0100
> The core module Time::Local + localtime() are sufficient to answer the
> FAQ question safely.
>
> use Time::Local;
> my $today = timelocal 0, 0, 12, ( localtime )[3..5];
> my ($d, $m, $y) = ( localtime $today-86400 )[3..5];
> printf "Yesterday: %d-%02d-%02d\n", $y+1900, $m+1, $d;
Added to the FAQ. Thanks,