What date was so many months and years before


G

George Mpouras

#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.



use strict;
use warnings;
use Time::Local 'timelocal_nocheck';


my $Months = 21;
my $Years = 4;


my $startfrom = $^T;
$Years += int $Months / 12;
$Months = $Months % 12;
my @STARTFROM = localtime $startfrom;
my $d = $STARTFROM[3];
my $m = 0;
my $y = 0;

if ( $Months <= $STARTFROM[4] )
{
$y = $STARTFROM[5] - $Years;
$m = $STARTFROM[4] - $Months
}
else
{
$m = 12 - $Months + $STARTFROM[4];
$y = $STARTFROM[5] - $Years - 1
}

my $max_month_days = How_many_days_have_a_month(1+$m, 1900+$y);
$d = $max_month_days if $d > $max_month_days;
my $backtime = Time::Local::timelocal_nocheck(@STARTFROM[0..2],
$d, $m, $y);



print "epoch : $backtime\n";
print "human : ", scalar(localtime $backtime) ,"\n";










# How_many_days_have_a_month(MONTH, YEAR)
# MONTH 1 .. 12
# YEAR e.g. 1970
#
sub How_many_days_have_a_month
{
my $month = $_[0];
my $year = $_[1];
my $days;
my $leap_year;

if ($year % 4)
{
$leap_year=0
}
elsif ($year % 100)
{
$leap_year=1
}
elsif ($year % 400)
{
$leap_year=0
}
else
{
$leap_year=1
}

if ($month == 1) {$days = 31}
elsif ($month == 2) {$days = $leap_year ? 29 : 28}
elsif ($month == 3) {$days = 31}
elsif ($month == 4) {$days = 30}
elsif ($month == 5) {$days = 31}
elsif ($month == 6) {$days = 30}
elsif ($month == 7) {$days = 31}
elsif ($month == 8) {$days = 31}
elsif ($month == 9) {$days = 30}
elsif ($month == 10) {$days = 31}
elsif ($month == 11) {$days = 30}
elsif ($month == 12) {$days = 31}
$days
}
 
Ad

Advertisements

J

Jürgen Exner

George Mpouras said:
#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.

Is there anything wrong with Date::Calc?

[long, awkward code snipped]

jue
 
G

George Mpouras

Στις 29/11/2013 15:51, ο/η Jürgen Exner έγÏαψε:
George Mpouras said:
#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.

Is there anything wrong with Date::Calc?

[long, awkward code snipped]

jue


Date::Calc is also fine.
this is happening when you do not take the correct turn early
 
R

Rainer Weikusat

Jürgen Exner said:
George Mpouras said:
#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.

Is there anything wrong with Date::Calc?

[long, awkward code snipped]

Replacing a small amount of 'awkward code' with a large amount of
'awkward code' isn't necessarily an improvement.
 
R

Rainer Weikusat

George Mpouras said:
#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.
[...]

# How_many_days_have_a_month(MONTH, YEAR)
# MONTH 1 .. 12
# YEAR e.g. 1970
#
sub How_many_days_have_a_month
{
my $month = $_[0];
my $year = $_[1];
my $days;
my $leap_year;

if ($year % 4)
{
$leap_year=0
}
elsif ($year % 100)
{
$leap_year=1
}
elsif ($year % 400)
{
$leap_year=0
}
else
{
$leap_year=1
}

if ($month == 1) {$days = 31}
elsif ($month == 2) {$days = $leap_year ? 29 : 28}
elsif ($month == 3) {$days = 31}
elsif ($month == 4) {$days = 30}
elsif ($month == 5) {$days = 31}
elsif ($month == 6) {$days = 30}
elsif ($month == 7) {$days = 31}
elsif ($month == 8) {$days = 31}
elsif ($month == 9) {$days = 30}
elsif ($month == 10) {$days = 31}
elsif ($month == 11) {$days = 30}
elsif ($month == 12) {$days = 31}
$days
}

--------
sub leap_year
{
return 0 if $_[0] & 3;
return !!($_[0] % 100 || !($_[0] % 400));
}


sub days_per_month
{
my ($m, $y) = @_;

return 28 + leap_year($y)
if $m == 2;

return 30 + (($m & 1) ^ ($m >= 8));
}

print(days_per_month($ARGV[0], $ARGV[1]), "\n");
--------

A long time ago, someone wrote on USENET that 'mathematics has to be
taught to people so that they learn to think'. I'll wonder if the poor
sod ever figures out that 'written tests' teach people how to copy
someone else's solution unnoticed ...
 
Ad

Advertisements

G

gamo

El 29/11/13 17:29, Rainer Weikusat escribió:
--------
sub leap_year
{
return 0 if $_[0] & 3;
return !!($_[0] % 100 || !($_[0] % 400));
}


sub days_per_month
{
my ($m, $y) = @_;

return 28 + leap_year($y)
if $m == 2;

return 30 + (($m & 1) ^ ($m >= 8));
}

print(days_per_month($ARGV[0], $ARGV[1]), "\n");

This seems excellent. How would you implement delta_days?

TIA
 
G

gamo

El 01/12/13 00:57, gamo escribió:
El 29/11/13 17:29, Rainer Weikusat escribió:
--------
sub leap_year
{
return 0 if $_[0] & 3;
return !!($_[0] % 100 || !($_[0] % 400));
}


sub days_per_month
{
my ($m, $y) = @_;

return 28 + leap_year($y)
if $m == 2;

return 30 + (($m & 1) ^ ($m >= 8));
}

print(days_per_month($ARGV[0], $ARGV[1]), "\n");

This seems excellent. How would you implement delta_days?

TIA


Here's all what my brain could make, using wour subs:

sub delta_days{
my ($d1, $m1, $y1, $d2, $m2, $y2) = @_;
my $delta =0;
my $ystep =1;
$ystep = -1 if $y1>$y2;
for (my $i=$y1; $i!=$y2; $i += $ystep) {
$delta += (365+leap_year($i))*$ystep;
}
my $mstep = 1;
$mstep = -1 if $m1>$m2;
for (my $j=$m1; $j!=$m2; $j += $mstep){
$delta += days_per_month($j)*$mstep;
}
$delta += ($d2-$d1);
return $delta;
}

TIA
 
J

Jürgen Exner

gamo said:
El 01/12/13 01:50, Jürgen Exner escribió:

Yes, thanks, I tryed that before and I encounter
extrange results.

http://www.telecable.es/personales/gamo/price.pl

Particulary with this function and Time_Date.
Maybe the differences are caused by the format
of the time: UTC then, CET now.

Well, if your dates are in different time zones then obviously your are
asking for trouble. So standardize to whatever single time zone you
prefer.
And when you do have your dates in some normalized format, then just
convert both into seconds since the epoch, compute the difference, and
divide by 24*60*60.
This is close enough for all practical purposes because when your output
unit is days then you don't care about leap seconds or hours
added/removed by summer time.

jue
 
Ad

Advertisements

G

gamo

El 01/12/13 10:00, Jürgen Exner escribió:
And when you do have your dates in some normalized format, then just
convert both into seconds since the epoch, compute the difference, and
divide by 24*60*60.
This is close enough for all practical purposes because when your output
unit is days then you don't care about leap seconds or hours
added/removed by summer time.

jue

perldoc -f time mentions the DateTime module. Anyway, there is a
problem with the epoch, that is a too recent date. I.e. if I want
to calculate my age in days I think it's better to count over the
actual calendar (gregorian). :-(

Thanks
 
C

Charlton Wilbur

RW> Replacing a small amount of 'awkward code' with a large amount
RW> of 'awkward code' isn't necessarily an improvement.

Replacing a small amount of incorrect code with a large amount of
correct code, however, is a significant improvement.

Your allergy to code other people have written is puzzling; why are you
not writing directly in x86 assembler?

Charlton
 
J

Jürgen Exner

gamo said:
El 01/12/13 10:00, Jürgen Exner escribió:

perldoc -f time mentions the DateTime module. Anyway, there is a
problem with the epoch, that is a too recent date. I.e. if I want
to calculate my age in days I think it's better to count over the
actual calendar (gregorian). :-(

If time since epoch is a signed integer then that would be no problem,
either.

jue
 
J

Jürgen Exner

Rainer Weikusat said:
Jürgen Exner said:
George Mpouras said:
#I want the calendar date of any number of years/months before.
# Currently I use the following, but maybe there is a better way.

Is there anything wrong with Date::Calc?

[long, awkward code snipped]

Replacing a small amount of 'awkward code' with a large amount of
'awkward code' isn't necessarily an improvement.

In my book a
use Date::Calc;
is significantly shorter than anything the OP wrote. Besides, chances
are much higher that it is correct.

But of course you are welcome to your own believes.

jue
 
C

Charlton Wilbur

BM> DateTime is the 'big guns' when it comes to date and time
BM> manipulation in Perl. It does everything, and it does it right,
BM> but it's also quite a large chunk of code. IME it's usually
BM> simpler just to use it anyway, though.

Simpler and wiser; the first time your code screws up because the
legislative entity in your country changed the dates for Daylight
Savings Time or British Summer Time or whatever it's called in your
locale, you will have wasted more time than just using DateTime.

Assuming you got the time change right in the first place, that is. I
worked for a place (years ago) that had custom date handling code.
Twice a year we could count on customer service nightmares because no
two systems handled daylight savings time in the same way, never mind
correctly.

Charlton
 
Ad

Advertisements

$

$Bill

Even 32bit machines have floating point numbers which provide 53 bits of
integer accuracy. Since 5.12 perl has used its own implementation of the
time_t functions which uses floats on 32bit machines to handle dates
beyond 2038.

True, but I was referring to the standard UNIX time functions which
were/are all integer arithmetic - not a Perl workaround.

Remember the Y2K issues - the next issue would have been the 2038
issue, but by then the computers will all be like 248 bitters. ;)
 
Ad

Advertisements

G

gamo

El 03/12/13 11:20, $Bill escribió:
Remember the Y2K issues - the next issue would have been the 2038
issue, but by then the computers will all be like 248 bitters. ;)

256 bits. Maybe. But the clock speed in Ghz seems difficult to
improve, comparing to the number of processor's cores. The branch
of the optical computers seems a dead way. I don't expect to
see what happens that year, but I predict that nobody will be
impressed with computers as we are today. Maybe the key will be
brain-machines interfaces.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top