The stupid question is the question not asked PerlMonks

### Arithmetic bug within Time:Piece?

by jeffa (Bishop)
 on Oct 02, 2015 at 19:34 UTC Need Help??

jeffa has asked for the wisdom of the Perl Monks concerning the following question:

Greetings! Given today's day, i would like to calculate 3 additional dates:

1. today - one week
2. today - one month
3. today - one year
This should be simple enough with Time::Piece, however i have found that i need to adjust the deltas for one month and one year by some very inconsistent amounts of time. Please consider the following code and its output:
```use strict;
use warnings;
use Time::Piece;
use Time::Seconds;

my \$now = localtime;
print "Today: \$now\n";
print " Week: ", \$now - ONE_WEEK, \$/;
print "  Mon: ", \$now - ONE_MONTH, \$/;
print " Year: ", \$now - ONE_YEAR, \$/;
print "\n";
print "Today: \$now\n";
print " Week: ", \$now - ONE_WEEK, \$/;
print "  Mon: ", \$now - ONE_MONTH + (ONE_HOUR * 10) + (ONE_MINUTE * 29
+) + 4, \$/;
print " Year: ", \$now - ONE_YEAR + (ONE_HOUR * 6) - (ONE_MINUTE * 11)
+- 10, \$/;

__DATA__
Today: Fri Oct  2 12:30:17 2015
Week: Fri Sep 25 12:30:17 2015
Mon: Wed Sep  2 02:01:13 2015
Year: Thu Oct  2 06:41:27 2014

Today: Fri Oct  2 12:30:17 2015
Week: Fri Sep 25 12:30:17 2015
Mon: Wed Sep  2 12:30:17 2015
Year: Thu Oct  2 12:30:17 2014
My specific question is why do i have to add 10 hours, 29 minutes and 4 seconds to the delta for last month, and 6 hours minus 11 minutes, 10 seconds to the delta for last year. Surely i am doing something wrong or not taking something into consideration. I have tested this on three separate Linux servers and received the same results.

jeffa

```L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
```

Replies are listed 'Best First'.
Re: Arithmetic bug within Time:Piece?
by CountZero (Bishop) on Oct 02, 2015 at 20:58 UTC
The constant ONE_MONTH is defined as 2_629_744 seconds, which is the number of seconds in one year divided by twelve and hence is some kind of "average" month, totally useless for your purpose.

The same problem happens with ONE_YEAR which is 31_556_930 seconds or the number of seconds in 365.24225 days

The fact that your year calculation was off by about one quarter of a day was a dead give-away.

CountZero

A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

My blog: Imperial Deltronics
Yep the POD talks about that differences of Time::Piece objects are returned as seconds Time::Seconds objects.

The only example given of adding a Time-Seconds' constant is ONE_DAY, which is mostly safe.

And the POD of Time::Seconds says that those constants are not objects but only seconds. ¹

The documentation is indeed misleading ... and unfortunately again a case were "core module" means "old module".

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

¹) Since perl does not (yet?) support constant objects, these constants are in seconds only, so you cannot, for example, do this: print ONE_WEEK->minutes;

> Since perl does not (yet?) support constant objects, these constants are in seconds only, so you cannot, for example, do this: print ONE_WEEK->minutes;

Could someone please enlighten me if this is an (old) problem?

I had no problems to store an object in a constant.

##### update
```use strict;
use warnings;

{
package MY_TIME;
sub print_sec {
my \$self =shift;
print \$self->[0];
}
}

use constant ONE_HOUR => bless [3600], "MY_TIME";

ONE_HOUR->print_sec;
__END__
3600

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

The documentation is indeed misleading ... and unfortunately again a case were "core module" means "old module".

By the way you mention this, it sounds like it's been well known. I've never put together ties between 'core' and `stale'. Are there other examples of this?

If so, my synopsis would be 'patch if one knows better'.

-stevieb

Re: Arithmetic bug within Time:Piece?
by toolic (Bishop) on Oct 02, 2015 at 20:13 UTC
I don't know the answer to your question, but the POD does mention add_months and add_years, which seem to work as you want:
```use strict;
use warnings;
use Time::Piece;
use Time::Seconds;

my \$now = localtime;
print "Today: \$now\n";
print " Week: ", \$now - ONE_WEEK, \$/;
print "  Mon: ", \$now - ONE_MONTH, \$/;
print "  Mon: ", \$now->add_months(-1), "\n";
print " Year: ", \$now - ONE_YEAR, \$/;
print " Year: ", \$now->add_years(-1), "\n";

__DATA__
Today: Fri Oct  2 16:12:17 2015
Week: Fri Sep 25 16:12:17 2015
Mon: Wed Sep  2 05:43:13 2015
Mon: Wed Sep  2 16:12:17 2015
Year: Thu Oct  2 10:23:27 2014
Year: Thu Oct  2 16:12:17 2014
Re: Arithmetic bug within Time:Piece?
by VinsWorldcom (Parson) on Oct 02, 2015 at 20:23 UTC

A quick read of the POD suggests you should use add_months() and add_years() to get accurate values. Adding the following just before your __DATA__ works for me on Windows 7 x64 / Strawberry 5.18.1.

```print "Done according to POD:\n";
print "  Mon: " . \$now->add_months(-1) . "\n";
print " Year: " . \$now->add_years(-1) . "\n";

UPDATE:

I don't need Time::Piece to verify that I'm 10 minutes too late as Toolic (above) beat me to it.

Re: Arithmetic bug within Time:Piece?
by u65 (Chaplain) on Oct 02, 2015 at 23:04 UTC

You might take a look at module Date::Calc which has served me well for all the date/time problems I've had.

I agree. Date::Calc is the "Swiss Army Knife" of date/time modules. Seldom ideal, but it always gets the job done.
Bill
"... Date::Calc...has served me well..."

I'm glad that i'm not alone.

Regards, Karl

P.S.: See Re^3: How To Modify PDF Metadata

«The Crux of the Biscuit is the Apostrophe»

Re: Arithmetic bug within Time:Piece?
by ww (Archbishop) on Oct 02, 2015 at 19:51 UTC

To help you stay in practice with manual calculation of DT differences?

Possible hint of problems, tho: in the doc under the heading "Date Parsing" where data starts out as "Sun" and the module returns "Wed", the author, Ricardo SIGNES, says "(see, it's even smart enough to fix my obvious date bug)."

I don't imagine that's a lot of help... but it exists (and to paraphrase the philosopher) therefore I cite it.

;-)

The Jeffa doesn't need help from sockpuppets like us! ;)

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1143675]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2019-05-22 06:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Do you enjoy 3D movies?

Results (138 votes). Check out past polls.

Notices?