What date was so many months and years before

Discussion in 'Perl Misc' started by George Mpouras, Nov 29, 2013.

  1. #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
    }
    George Mpouras, Nov 29, 2013
    #1
    1. Advertising

  2. George Mpouras <> wrote:
    >#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
    Jürgen Exner, Nov 29, 2013
    #2
    1. Advertising

  3. Στις 29/11/2013 15:10, ο/η Henry Law έγÏαψε:
    > On 29/11/13 11:57, George Mpouras wrote:
    >> #I want the calendar date of any number of years/months before.

    >
    > Here's a useful web site:
    >
    > http://search.cpan.org/search?query=date calculation



    The same with Date::Manip

    use Date::Manip;
    my $date = new Date::Manip::Date;
    $date->parse("epoch $^T");
    $date->parse('-4:-21:0:0:0:0:0');
    print $date->printf('%d %b %Y %H:%M');


    : )
    George Mpouras, Nov 29, 2013
    #3
  4. Στις 29/11/2013 15:51, ο/η Jürgen Exner έγÏαψε:
    > George Mpouras <> wrote:
    >> #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
    George Mpouras, Nov 29, 2013
    #4
  5. Jürgen Exner <> writes:
    > George Mpouras <> wrote:
    >>#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.
    Rainer Weikusat, Nov 29, 2013
    #5
  6. George Mpouras <> writes:
    > #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 ...
    Rainer Weikusat, Nov 29, 2013
    #6
  7. George Mpouras

    gamo Guest

    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
    gamo, Nov 30, 2013
    #7
  8. gamo <> wrote:
    >How would you implement delta_days?


    use Data::Calc;
    $Dd = Delta_Days($year1,$month1,$day1,
    $year2,$month2,$day2);


    jue
    Jürgen Exner, Dec 1, 2013
    #8
  9. George Mpouras

    gamo Guest

    El 01/12/13 01:50, Jürgen Exner escribió:
    > gamo <> wrote:
    >> How would you implement delta_days?

    >
    > use Data::Calc;
    > $Dd = Delta_Days($year1,$month1,$day1,
    > $year2,$month2,$day2);
    >
    >
    > jue
    >


    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.

    Best regards
    gamo, Dec 1, 2013
    #9
  10. George Mpouras

    gamo Guest

    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
    gamo, Dec 1, 2013
    #10
  11. gamo <> wrote:
    >El 01/12/13 01:50, Jürgen Exner escribió:
    >> gamo <> wrote:
    >>> How would you implement delta_days?

    >>
    >> use Data::Calc;
    >> $Dd = Delta_Days($year1,$month1,$day1,
    >> $year2,$month2,$day2);

    >
    >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
    Jürgen Exner, Dec 1, 2013
    #11
  12. George Mpouras

    gamo Guest

    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
    gamo, Dec 2, 2013
    #12
  13. >>>>> "RW" == Rainer Weikusat <> writes:

    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


    --
    Charlton Wilbur
    Charlton Wilbur, Dec 2, 2013
    #13
  14. gamo <> wrote:
    >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). :-(


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

    jue
    Jürgen Exner, Dec 2, 2013
    #14
  15. Rainer Weikusat <> wrote:
    >Jürgen Exner <> writes:
    >> George Mpouras <> wrote:
    >>>#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
    Jürgen Exner, Dec 2, 2013
    #15
  16. >>>>> "BM" == Ben Morrow <> writes:

    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


    --
    Charlton Wilbur
    Charlton Wilbur, Dec 2, 2013
    #16
  17. George Mpouras

    $Bill Guest

    On 12/2/2013 08:03, Jürgen Exner wrote:
    > gamo <> wrote:
    >
    >> 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.


    Has to be unsigned if it goes to 2038 and you're on a 32 bitter. :)
    $Bill, Dec 3, 2013
    #17
  18. George Mpouras

    $Bill Guest

    On 12/3/2013 00:28, Ben Morrow wrote:
    >
    > Quoth "$Bill" <>:
    >>
    >> Has to be unsigned if it goes to 2038 and you're on a 32 bitter. :)

    >
    > 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. ;)

    > (And 'dates after 2038' is the problem, not 'dates before 1970'. time_t
    > has always been signed.)
    $Bill, Dec 3, 2013
    #18
  19. George Mpouras

    gamo Guest

    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.
    gamo, Dec 3, 2013
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Grison

    Date, date date date....

    Peter Grison, May 28, 2004, in forum: Java
    Replies:
    10
    Views:
    3,229
    Michael Borgwardt
    May 30, 2004
  2. raghav

    Years to Months Conversion

    raghav, Sep 22, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    305
    raghav
    Sep 26, 2006
  3. dare ruby
    Replies:
    2
    Views:
    96
    dare ruby
    Feb 12, 2010
  4. Replies:
    4
    Views:
    539
    Lasse Reichstein Nielsen
    Jun 20, 2006
  5. Erich93063

    See if date is within last three years.

    Erich93063, May 3, 2011, in forum: Javascript
    Replies:
    18
    Views:
    216
    Mike Duffy
    May 8, 2011
Loading...

Share This Page