道歉,如果這是一個非常簡單的問題,但我有興趣嘗試達到準確的答案,而不僅僅是一個「四捨五入」的答案。從特定日期的年齡計算出生日期[MySQL或Perl]
我的問題是:我知道有人是2008年3月18日27.12(隨機例子)。我怎樣才能以最接近的近似值計算他的出生日期。年齡始終以實際數字提供至兩位小數點。
道歉,如果這是一個非常簡單的問題,但我有興趣嘗試達到準確的答案,而不僅僅是一個「四捨五入」的答案。從特定日期的年齡計算出生日期[MySQL或Perl]
我的問題是:我知道有人是2008年3月18日27.12(隨機例子)。我怎樣才能以最接近的近似值計算他的出生日期。年齡始終以實際數字提供至兩位小數點。
eumiro的答案是訣竅;以下使用Time::Piece模塊(自5.10起與Perl捆綁在一起)可能更易於維護。
use strict;
use warnings;
use 5.010;
use Time::Piece;
use Time::Seconds;
my ($date, $age) = ('2008-03-18', 27.12);
my $birthday = Time::Piece->strptime($date, '%Y-%m-%d') - $age*ONE_YEAR;
say $birthday->ymd();
由於該年齡段缺乏準確性(1/100年),這會在實際生日的幾天內得到您。
use strict;
use Time::Local;
my $now = timelocal(0, 0, 12, 18, 3-1, 2008);
my $birthday = $now - 27.12 * 365.25 * 86400;
print scalar localtime $birthday;
返回Mon Feb 2 22:04:48 1981
。
您的精度爲0.01年,大致爲3天,因此您甚至無法涵蓋所有生日。
我的方法並沒有很好地涵蓋閏年,但是你無法真正用它們來計算。想象一下2008年3月1日。在這個日期之前什麼日期是「1年零一天」? 2007年2月28日或2007年2月29日不存在?
由於四捨五入,通過簡單分數計算的解決方案是1981-02-03和前一天。正如eumiro所說,1/100年的分辨率還不夠精確,所以在實際的日期可能還有一兩天。
use DateTime qw();
use POSIX qw(modf);
my $date = DateTime->new(year => 2008, month => 3, day => 18); # 2008-03-18
my $age = 27.12; # 27.12
my ($days, $years) = modf $age; # (0.12, 27)
$days *= 365.25; # 43.83
# approx. number of days in a year, is accurate enough for this purpose
$date->clone->subtract(years => $years, days => $days); # 1981-02-03
$date->clone->subtract(years => $years, days => 1 + $days); # 1981-02-02
一種允許更高精度的方法只需利用現有的MySQL日期/時間函數。如果在MySQL內部工作,可以通過在TO_SECONDS()轉換中將兩個日期中的每一個轉換爲秒來非常精確地計算年齡,然後將結果操作爲期望的精度。在這些情況下,日期爲'yyyy-mm-dd hh:mm:ss'格式,假定一年的平均長度爲365.242天。
ROUND((TO_SECONDS(AnyDateTime) - TO_SECONDS(出生日期))/(365.242 * 60 * 60 * 24),3)年齡, 如:
ROUND((TOSECONDS('2013-01-01 00:00:00') - TO_SECONDS('1942-10-16')/(365.242*60*60*24),3) as AGE --> 70.214
或者你可以使用DATEDIFF( )轉換,它提供了幾天的答案:
ROUND(DATEDIFF('2013-01-01 00:00:00','1942-10-16')/365.242,3) AS age --> 70.214
-1忘記閏日 – daxim 2011-01-25 12:30:35