Re: Date Manipulation Calculation Question
by duff (Parson) on Nov 01, 2004 at 23:18 UTC
|
use POSIX qw(strftime);
$now = time;
$then = $now - 15 * 60; # 15 minutes ago;
print map strftime("%Y%m%d%H%M%S\n", localtime($_)), $now, $then;
All code untested, but use something like that rather than call the date(1) command.
| [reply] [d/l] |
Re: Date Manipulation Calculation Question
by tachyon (Chancellor) on Nov 01, 2004 at 23:34 UTC
|
As duff points out time will give you the time in seconds since the epoch so it is easy to add or subtract whatever you want. gmtime and its friend localtime convert epoch seconds into all the date bits when called in list context or a nice human readable string when called in scalar context.
my $epoch = time();
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($epo
+ch);
my $gm_str = gmtime(); # note that default epoch for gmtime is NOW()
printf '%d seconds
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = %s
%s
%s
', $epoch, "($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)", $g
+m_str,
scalar(localtime); # need scalar(localtime) as print has list context
__DATA__
1099351947 seconds
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = (27,32,23,1,10
+,104,1,305,0)
Mon Nov 1 23:32:27 2004
Tue Nov 2 10:32:27 2004
| [reply] [d/l] |
Re: Date Manipulation Calculation Question
by Kyoichi (Novice) on Nov 01, 2004 at 23:25 UTC
|
I'd recommend that you use localtime and then substract the number of seconds of 15 minutes ( that is 60*15 ), and then you can convert to whatever format you want with POSIX::strftime.
If that solution is not that good, I suggest for you to take a look on Date::Manip and Time::Local for your doings.
Greetings | [reply] |
Re: Date Manipulation Calculation Question
by poqui (Deacon) on Nov 01, 2004 at 23:25 UTC
|
use DateTime;
CPAN
It puts the DateTime in a struct that makes it easier to manipulate. | [reply] |
Re: Date Manipulation Calculation Question
by pg (Canon) on Nov 02, 2004 at 03:05 UTC
|
On a 32-bit machine, the valid range of epoch is: 0 - 2 ** 31 - 1 inclusive, and they translate into:
1970 January 01 00:00:00
2038 January 19 03:14:07
Here is the code:
use POSIX;
{
my $t = strftime("%Y %B %d %H:%M:%S", gmtime(0));
print $t, "\n";
}
{
my $t = strftime("%Y %B %d %H:%M:%S", gmtime(2 ** 31 - 1));
print $t, "\n";
}
| [reply] [d/l] [select] |
Re: Date Manipulation Calculation Question - performance alternative
by PhilHibbs (Hermit) on Nov 02, 2004 at 14:06 UTC
|
Most everyone has replied with some form of "Convert it to seconds, do the math, convert it back again". This is an entirely acceptable answer, and absent any other requirements this is what I would do.
There is, however, a possible reason not to do this if performance is an issue. Note that there would have to be a really good reason to do it this way, but here goes.
Converting a string such as 20041101174146 to a number of seconds would take at least 6 mathematical operations for the 2004, 11, 01, 17, 41, and 46 components. Converting it back again will take another 6, then there's either the string splitting or modulus operations to break it up, and the opposites to put it back again. This could entail 25 discrete steps.
In most cases, and certainly with the example above, this can be done with a substring, a subtract, a test for undererflow, and an assignment back to the substring. It is possible that adding a value to a time string such as the above could cause 5 overflows (19991231235959 + 1 second = 20000101000000), and this case would take considerably more computation than the generic convert-to-seconds approach, but in most cases there should be a performance gain. | [reply] |
|
|
Converting a string such as 20041101174146 to a number of seconds would take at least 6 mathematical operations for the 2004, 11, 01, 17, 41, and 46 components.
Well, one thing to recall here is that if the operation occurs regularly then caching the results will result in a signifigant speedup. For instance you could cache the year/month/day/hour results and then add in only the minutes and seconds. This means that a lot of the operations you mention here wouldn't have to happen unless the cache was empty and even then would only happen once.
After a LOT of benchmarking I found the following routine works best for my situation (parsing millions of datestamps a day), obviously other usage cases may have different performance effects.
{
my (%hourcache,%mincache);
sub D14_to_unix {
my $hour = substr( $_[0], 0, 10 );
my $min = substr( $_[0], 10, 4 );
return +( $hourcache{$hour} ||=
timelocal( 00,
00,
substr( $hour, 8, 2 ),
substr( $hour, 6, 2 ),
substr( $hour, 4, 2 ) - 1,
substr( $hour, 0, 4 ) - 1900
)
) + ( $mincache{$min} ||=
( substr( $min, 0, 2 ) * 60 + substr( $min, 2, 2 ) )
);
}
}
| [reply] [d/l] |
Re: Date Manipulation Calculation Question
by TedPride (Priest) on Nov 02, 2004 at 13:04 UTC
|
@_ = localtime(time()-900);
my $RunDateTime = ($_[5]+1900).sprintf('%02d%02d%02d%02d%02d',($_[4]+1
+),$_[3],$_[2],$_[1],$_[0]);
This does what you want, but without the overhead of using a module or calling the system through ` `. | [reply] [d/l] |
Re: Date Manipulation Calculation Question
by TomDLux (Vicar) on Nov 02, 2004 at 16:45 UTC
|
How many million dates do you need to process per hour?
Unless it's significant, modules are definitely your friend.
I hate having to fix bugs because people thought it was too
expensive to load a module, and so wrote their own routine
to calculate, for example, "previous business day". Something
changes in the input, or you come along to the leap year in
the century which isn't a leap year, or the one in four centuries
which IS a leap year, after all, and things don't work. Far better to
use some code which has solved all those problems.
I would suggest using unpack() to parse the
date into variables, timelocal() to convert to
epoch seconds, and strftime or sprintf to convert back to a
timestamp.
$t1 = 20041101174146
my ( $y, $m, $d, $hh,$mm, $ss ) = unpack ("A4A2A2A2A2A2", $a )
$epoch= timelocal( $ss, $mm, $hh, $d, $m-1, $y-1900 )
( $ss, $mm, $hh, $d, $m, $y ) = localtime( $epoch - $seconds_to_subtra
+ct)
$t2 = sprintf( "%d%02d%02d%02d%02d%02d", $y+1900, $m+1, $d, $hh, $mm,
+$ss );
# $t2 is 20041101172646
Once you have your code working correctly, profile it.
If time conversion is a major factor, you can look at writing custom conversions.
But even then, leave the ordianry code in a routine so your testing can compare
the two results, to ensure things are correct.
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] [d/l] |
Re: Date Manipulation Calculation Question
by TedPride (Priest) on Nov 02, 2004 at 14:52 UTC
|
The object of getting the date / time in a fixed length string like this is to be able to perform comparisons on log file lines. Unless you have access to the log script and can change the time format to timestamp, time / localtime / sprintf is about as efficient as you can get. | [reply] |
Re: Date Manipulation Calculation Question
by geektron (Curate) on Nov 02, 2004 at 22:37 UTC
|
i've been using Date::Calc and Add_Delta_* for things like this ... | [reply] |
Re: Date Manipulation Calculation Question
by Anonymous Monk on Nov 04, 2004 at 13:11 UTC
|
use maketime. Perl has Cs maketime library built-in which is very good for dealing with dates. Do a search on maketime for examples. | [reply] |