Calculating delta years from a date

I'm trying to figure out a way to calculate the year of birth for records when it is given the age of up to two decimal places on a specific date - in Perl.

To illustrate this example, consider these two entries:

date, age at date
25 Nov 2005, 74.23
21 Jan 2007, 75.38

What I want to do is get the year of birth based on these records - it should be, theoretically, consistent. The problem is that when I try to get it by calculating the difference between the year in the date field minus age, I encounter rounding errors, as a result of which the results look wrong, while they are actually correct.

I tried to use some kind of smart combination of int () or sprintf () to round, but not use. I looked at Date :: Calc but can't see what I can use.

ps Like many dates before 1970, I cannot, unfortunately, use the UNIX era for this.

+3
source share
4 answers

Perl functions gmtimeand localtimehave no problems handling negative input and dates before 1970.

use Time::Local;
$time = timegm(0,0,0,25,11-1,2005-1900);          # 25 Nov 2005
$birthtime = $time - (365.25 * 86400) * 74.23;    # ~74.23 years
print scalar gmtime($birthtime);                  # ==> Wed Sep 2 11:49:12 1931

The actual date of birth may vary by several days, as one hundredth of a year gives you a resolution of 3-4 days.

+4
source

Have you tried DateTime ? It will handle both parsing and subtraction.

+6
source

DateTime DateTime:: Duration.

DateTime:: Duration DateTime, DateTime.

use strict;
use warnings;
use DateTime::Format::Strptime;
use DateTime::Duration;

my $fmt = DateTime::Format::Strptime->new(
    pattern => '%d %b %Y',
    locale  => 'en_US',
);

my $start = $fmt->parse_datetime($ARGV[0]);
my $age = DateTime::Duration->new(years => $ARGV[1]);

my $birth = $start - $age;
print $fmt->format_datetime($birth), "\n";

, :

$ perl birth.pl "25 Nov 2005" 74.23
25 Sep 1931
$ perl birth.pl "21 Jan 2007" 75.38
21 Sep 1931
+2

Oesor ( ) mobrule , perl . DateTime .

, POSIX::mktime:

my ( $year1, $mon1, $day1 ) = qw<1944 7 1>;
my ( $year2, $mon2, $day2 ) = qw<2006 5 4>;

my $time1 = POSIX::mktime( (0) x 3, $day1, $mon1 - 1, 72 );
my $time2 = POSIX::mktime( (0) x 3, $day2, $mon2 - 1, 72 );
my $years = $year2 - $year1 - ( $time2 < $time1 ? 1 : 0 );
# 61 years

The caveat is that perl internal watch handlers date back to December 14, 1902 (actually 13, in the afternoon and until 6 p.m.), before which mktime starts to return undef. Thus, for 99% of people living today, this is likely to be.

Pointless little things: scalar localtime( 0x80000000 ) : 'Fri Dec 13 15:45:52 1901' <- what circumcision ( 0x80000000is the minimum integer with two additions)

+1
source

Source: https://habr.com/ru/post/1750334/


All Articles