Re: Calculating between times
by Joost (Canon) on Jan 08, 2004 at 18:01 UTC
|
I need to know how to make today's date (localtime()) put the day, month and year in a format like: 01.08.04.
I use POSIX::strftime() for most of my date formatting.
Can someone show me how I would compare a date string like 01.08.04 with a different $time?
If you have your times in seconds since epoch (and you don't care about too much exactness:
if ($time < time - $days * 24 * 60 * 60) { .... }
If you have formatted dates, or higher standards, go for Date::Manip.
HTH,
Joost.
| [reply] [d/l] |
|
|
What do you mean by epoch? Just an idea, is it possible to save $time in a huge mess like 1233455763432 where I could always subtract it from earlier times? If so, how could I do that? I could just setup another hash just for times like this and not worry about playing with the formatting.
| [reply] |
|
|
What do you mean by epoch?
See the documentation for the time function.
Just an idea, is it possible to save $time in a huge mess like 1233455763432 where I could always subtract it from earlier times?
Yes, that's what the time function returns.
Joost.
| [reply] |
Re: Calculating between times
by ysth (Canon) on Jan 08, 2004 at 18:02 UTC
|
For the leading zero problem, use sprintf:
$formatted_date = sprintf "%.2d.%2d.%2d", $mon+1, $mday, $year%100;
Update: everything from this point on, except the very last sentence, is intended mainly for humor value. For practical advice, go straight to the end.
For the other issue, just convert your day,month,year into a number of days since a fixed date, e.g.:
=head2 greg2rd
$rd = greg2rd( $year, $month, $day );
Convert gregorian year,month,day to days on or after Jan 1, 1 CE
(Gregorian). Normalization is performed (e.g. month of 28 means
April two years after given year) for month < 1 or > 12 or day < 1
or > last day of month.
=cut
sub greg2rd {
use integer;
my ( $y, $m, $d ) = @_;
my $adj;
# make month in range 3..14 (treat Jan & Feb as months 13..14 of p
+rev year)
if ( $m <= 2 ) {
$y -= ( $adj = ( 14 - $m ) / 12 );
$m += 12 * $adj;
} elsif ( $m > 14 ) {
$y += ( $adj = ( $m - 3 ) / 12 );
$m -= 12 * $adj;
}
# make year positive (oh, for a use integer 'sane_div'!)
if ( $y < 0 ) {
$d -= 146097 * ( $adj = ( 399 - $y ) / 400 );
$y += 400 * $adj;
}
# add: day of month, days of previous 0-11 month period that began
+ w/March,
# days of previous 0-399 year period that began w/March of a 400-m
+ultiple
# year, days of any 400-year periods before that, and -306 days to
+ adjust
# from Mar 1, year 0-relative to Jan 1, year 1-relative (whew)
$d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 +
( $y / 100 * 36524 + $y / 400 ) - 306;
}
# is date $formatted_then more than $autodelete days ago?
($mon,$mday,$year) = (localtime)[4,3,5];
$now = greg2rd($year+1900, $mon+1, $day);
($mon,$mday,$year) = split /\./, $formatted_then;
$then = greg2rd($year+1900, $mon, $day);
delete if ($now - $then > $autodelete);
Or instead of going to all of that bother, learn one of the fine modules that handle dates for you: DateTime,Date::Calc,Date::Manip. | [reply] [d/l] [select] |
Re: Calculating between times
by crabbdean (Pilgrim) on Jan 08, 2004 at 19:00 UTC
|
I've always found that when doing calcuations for things as in your example (eg. things older than x days) it can be easier to leave it in the time format of "seconds since the epoch". This way you can simply get your result by finding anything older than x days (times the number of seconds in those days eg "X" times 24 hours times 60 seconds times 60 seconds.
For example work got me to write a script to purge our share drive everyday of any files older than 7 days. Instead of adjusting times bewtween times formats I read the creation and modified dates for each file and simply compared them to a current time stamp. If the files mod time and creation time where both greater then 7*24*60*60 seconds I delete them.
Its easier to compute things to a base and then work from that base. Seconds is a good base.
If you have time in a mm/dd/yy format push this through the Time::Local() module of Perl to convert it back seconds. This module is the inverse of the localtime() function.
Also the Date::Calc module should blow your hair back as far as date calcuations go.
As for the leading zero try this:
#!perl
$var = 5;
$var = "0".$var if (length($var) < 2);
print $var;
Dean | [reply] [d/l] |
|
|
It turns out I can't use epoch. The way it's setup, I have three pull down menus (one for each: day, month, year) then I join them my $newdate = join(".", $day, $month, $year). And since that's as specific as the time is, I can't calculate epoch as a way to determine how long ago it was.
| [reply] |
|
|
| [reply] |
Re: Calculating between times
by Art_XIV (Hermit) on Jan 08, 2004 at 18:26 UTC
|
use warnings;
use strict;
use Date::EzDate;
my $date1 = Date::EzDate->new('01/01/2003');
my $date2 = Date::EzDate->new('1 October 2003');
my $before = '';
$before = 'not ' if $date1 >= $date2;
print $date1->{'%D'}, ' is ', $before, 'before ', $date2->{'%D'}, "\n"
+;
Hanlon's Razor - "Never attribute to malice that which can be adequately explained by stupidity"
| [reply] [d/l] |
Re: Calculating between times
by Paulster2 (Priest) on Jan 08, 2004 at 21:11 UTC
|
Date::Manip allows you to do many things with dates, including checking equality between two dates not formatted the same. You can also do all kinds of conversions. The perldoc is quite extensive, yet clear as to useage. As stated above in a previous Re:, get to know this bad boy, I don't think you will ever go back.
| [reply] |
Re: Calculating between times
by Anonymous Monk on Jan 08, 2004 at 20:50 UTC
|
You can format your output, as another poster noted, with printf or sprintf; The code below does that. To find the difference between dates, you can use module Time::Local and it's function, timelocal().
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
printf("Today's date is: %02d.%02d.%02d\n",
$mon+1, $mday, $year % 100);
my $date = "12.25.03";
my ($m,$d,$y) = split /\./, $date;
my $xmas_time = timelocal(0,0,0,$d,$m-1,$y);
my $today = time;
my $days_diff = int( ($today - $xmas_time) / (24*60*60) );
print "Difference is $days_diff days\n";
Chris | [reply] [d/l] |
|
|
Your code worked great! The only problem with that was you had month.day.year . I tried changing the script to allow the new format but I can't seem to get it to work now. The script below prints these results:
05.05.06
09.03.04
31.02.04
15.01.04
16.01.04
15.01.04
01.01.04
01.01.04
14.09.04
01.01.04
01.01.04
01.01.04
04.05.06
Day: 05 Month: 05 Year: 06
Day: 09 Month: 03 Year: 04
Software error:
Day '31' out of range 1..29 at line 43
Can you help me set it up so it works in this new format? it always dies on the third entry because the day is 31 when the error says it can only be 1..29.
Thank you!
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
my $today = time;
print "$today<br><br>";
foreach (keys %entries)
{
my ($date, $course, $location, $job_type, $contact) = split(/::/, $e
+ntries{$_});
print "$date<br>";
}
foreach (keys %entries)
{
my ($date, $course, $location, $job_type, $contact) = split(/::/, $e
+ntries{$_});
my ($d,$m,$y) = split /\./, $date;
my $saved_date = timelocal(0,0,0,$d,$m-1,$y);
my $days_diff = int( ($today - $saved_date) / (24*60*60) );
print "Day: $d Month: $m Year: $y<br>";
}
| [reply] [d/l] [select] |
|
|
Last I checked, February, being the second month, doesn't in fact have 31 days. If you expected that to be March, then you have an off by one error and you should add one to the month column before attempting to format it.
On the other, if you expect february to have 31 days, well, you have more problems then these perl ones!
| [reply] |
|
|
|
|
|
|
|
|
Re: Calculating between times
by Anonymous Monk on Jan 08, 2004 at 18:57 UTC
|
I will try to reask my questions in a better way..
Question 1) How can I get localtime() to print the day, month and year in this format 01.08.04 (if the day or month is less than 10, have a leading zero).
Question 2) After localtime is in it's nice little format, how do I check it against an already saved $time to determine if the date has already passed? I need to make it detect whether or not the saved date is more than a week old.
Thanks again | [reply] |
|
|
| [reply] [d/l] [select] |