计算从日期开始的年份增量

时间:2010-06-16 16:48:41

标签: perl datetime date

我试图找出一种方法来计算记录的出生年份,在给定日期给出两位小数的年龄 - 在Perl中。

为了说明这个例子,请考虑以下两个记录:

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

我想要做的是根据这些记录获得出生年份 - 从理论上讲,它应该是一致的。问题在于,当我尝试通过计算日期字段中年份与年龄之间的差异来推导它时,我遇到了舍入错误,导致结果看起来错误,而实际上它们是正确的。

我尝试使用int()或sprintf()的一些“聪明”组合来完善但无济于事。我看过Date :: Calc但是看不到我能用的东西。

P.S。由于许多日期都是在1970年之前,我不能不幸地使用UNIX纪元。

4 个答案:

答案 0 :(得分:6)

你试过DateTime吗?它将处理解析和减法。

答案 1 :(得分:4)

Perl的gmtimelocaltime函数在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

实际的生日可能会有几天不同,因为一年中只有一百分之一只能给你3-4天的分辨率。

答案 2 :(得分:2)

使用DateTime和DateTime :: Duration。

当您从DateTime中减去Date Time :: Duration时,您将获得另一个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

答案 3 :(得分:1)

我是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

需要注意的是,perl的内部时钟可以追溯到1902年12月14日(实际上是第13天,中午之后和下午6点之前),然后mktime开始返回undef。因此,对于99%的今天活着的人来说,这可能会有所作为。

毫无意义的琐事: scalar localtime( 0x80000000 ) : 'Fri Dec 13 15:45:52 1901'&lt; - 这就是截止(0x80000000是2s补全最小整数)