2010-06-16 10 views
3

주어진 날짜에 Perl에서 나이를 두 자리로 줄 때 레코드의 생년을 계산하는 방법을 알아 내려고합니다. 날짜로부터의 델타 계산하기

이 예제는이 두 기록을 고려 설명하기 :

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

는 내가 뭘 원하는 레코드를 기반으로 탄생 해 얻을 - 그것은해야한다 이론적으로 일관. 문제는 날짜 필드에서 연도 - 연도의 차이를 뺀 값을 계산하여이를 파생 시키려고 시도 할 때 반올림 오류가 발생하여 실제로 잘못된 결과가 나타나는 것입니다.

int() 또는 sprintf()의 "영리한"조합을 사용하여 문제를 해결했지만 사용하지 않으려 고 시도했습니다. 나는 Date :: Calc를 보았지만 사용할 수있는 것을 볼 수 없다.

p.s. 1970 년 이전의 많은 날짜들이 있기 때문에 유감스럽게도 유닉스 시대를 사용할 수는 없습니다.

+1

각 백 얼마나 많은 일을 상징 하는가 : 여기

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"; 

그것을 호출하는 방법에 대한 예입니다? (몇 가지 대답이 가능합니다.) – ysth

+0

이전 1970은 문제가 아닙니다. Unix time()은 부호있는 정수입니다. 그러나 사용하지 않는 더 좋은 이유가 있습니다. 윤년, 윤년 초 ... – dolmen

답변

4

펄의 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 일의 결의안.

+0

감사합니다 -이 작동하는 것 같습니다. 나는 1970 년 이전의 날짜를 처리하는 데 문제가있는 것처럼 보이는 Date :: Calc를 사용하고있었습니다. 나는 단지 몇 년을 비교할 것이기 때문에 해상도는 문제가되지 않습니다. – Spiros

+1

시스템에 따라,'gmtime' 계열의 함수 *는 1902 년 이전이나 2038 년 후에 문제가 될 수 있습니다. 여러분의 perl이이 중 하나이고 100 세가 될 가능성이 있다면, 안전을위한'DateTime'. – hobbs

6

DateTime을 사용해 보셨습니까? 파싱과 뺄셈을 처리합니다. 일년 중 하나 한 백은 당신에게를 제공하기 때문에

+0

팁 주셔서 감사합니다. - 사용해 본적이 없지만 나중에 참조 할 수 있도록 노력하겠습니다. – Spiros

1

두 번째 Oesor의 추천 (오늘 두 번째)은 perl이 부정적인 날짜를 처리한다는 mobrule의 알림을 반복합니다. 따라서 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 

주의해야 할 점은 그 펄의 내부 시계는 12 월 14, 실제로 1902 (13 일 다시 날짜를 처리하고, 정오 이후 오후 6시 전에), mktime이 undef을 반환하기 시작합니다. 따라서 오늘날 살아있는 사람들의 99 %에게 이것은 아마도 가능할 것입니다.

무의미 퀴즈 :scalar localtime(0x80000000) : 'Fri Dec 13 15:45:52 1901' <는 - 그 컷오프 (0x80000000되는 2S-보완 최소 정수)

2

사용 날짜 시간 및 날짜 시간 : 시간입니다.

DateTime :: Duration을 DateTime에서 빼면 다른 DateTime이 표시됩니다.

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

Hummm, 당신은'$ age = DateTime :: Duration-> new (years => $ ARGV [1]);를 사용하고 $ ARGV [1]은 74.23이지만, Date :: Manip for new (. ..) : 이 메서드는 "years", "months", "weeks", "days", "hours", "minutes", "seconds", "nanoseconds"및 "end_of_month"매개 변수를 사용합니다. "end_of_month"를 제외한 모든 항목이 숫자입니다. 숫자 중 하나라도 음수이면 전체 기간이 음수입니다. ** 모든 숫자는 정수 여야합니다. ** 정수가 아닌 숫자를 사용할 때 문제가 발생 했습니까? –