Есть ли Perl-эквивалент SAS-функции INTNX или Javascript-функции Dateadd? - PullRequest
2 голосов
/ 17 декабря 2009

Я пытаюсь преобразовать китайскую лунную систему в григорианский, используя Perl, как для развлечения, так и для обучения. Я думал, что есть какой-то простой математический алгоритм для выполнения этой работы, но оказалось, что я ошибался. В любом случае, после небольшого поиска, я наткнулся на некоторый готовый код SAS, который мог бы выполнить эту работу. Что ж, мне было не сложно понять, как переписать большую часть кода на Perl. Но есть что-то вроде этого:

Convert2Gregorian = INTNX ('day', conDate, AddDay-1);

Google сообщает мне, что INTNX - это функция, которая может возвращать дату, после которой был добавлен определенный интервал дат. Но использование ключевых слов «Perl INTNX» не дало мне ничего полезного. Затем я нашел сценарий, написанный на Javascript, общий подход примерно такой же, за исключением того, что Javascript использует функцию Dateadd, что-то вроде:

Return DateAdd(DateInterval.Day, AddDay - 1, conDate) 

Я также попытался выполнить поиск с использованием PPM, но не смог найти нужный модуль. Может ли кто-нибудь дать мне несколько советов?

Заранее спасибо:)

Обновление

Благодаря @psilva и @hobbs:)

Хаха, наконец-то я могу перевести один язык программирования на другой. Это весело :) Просто для удовольствия и, возможно, для дальнейшего использования: Вот оригинальный код SAS и код Perl, переведенный мной. Поправь меня, если я ошибаюсь:)

Примечание: данные неполные.

SAS-КОД КАК СЛЕДУЕТ:

data DateNtoG (drop = Ngstrings conDate AddMonth AddDay Mrunyue I);
array NGlist{43} $18_TEMPORARY_(
"010110101010170130" /*(1968)*/
"010101101010000217" /*(1969)*/
"100101101101000206" /*(1970)*/
"010010101110150127" /*(1971)*/
);

input tYear tMonth tDay RunYue;

if (tyear >1967 and tyear<2011) then do;
NGstrings = NGlist(tYear - 1967);
conDate = MDY (substr (NGstrings,15,2),(NGstrings, 17,2), tYear);

AddMonth = tMonth;

select (substr(NGstrings, 14, 1));
when ("A" )  Mrunyue=10;
when ("B" )  Mrunyue=11;
when ( "C" ) Mrunyue=12;
otherwise Mrunyue = substr (NGstrings, 14,1);
end;

if ((RunYue=1) and (tMonth=Mrunyue) ANDMrunyue>0)or ((tMonth Mrunyue) AND Mrunyue>0) then
do;
Addmonth = tMonth+1;
end;

AddDay = tDay;
do i = 1 To AddMonth-1;
AddDay = AddDay + 29 + substr(NGstrings,i,1);
end;

dNtoG = INTNX ('day', conDate, AddDay - 1);
put "Transfereddate:" dNtoGdate9.;
end;

ПЕРЕВОДНОЙ Perl-код, как следует: не обрабатывал неопределенные ситуации на данный момент

(Я изменил исходные имена переменных SAS)

#!perl

# A Chinese-Gregorian Calendar System Converter just for Testing

use Date::Calc qw(Add_Delta_Days); 
use integer;
use strict;
use warnings;

$_ = shift @ARGV;

if (length == 8) {
    $_.=0;
}

my ($Lunar_Year,$Lunar_Month,$Lunar_Day,$Leap_Month) = /(\d\d\d\d)(\d\d)(\d\d)(\d)/;


my %Lunar_Year_Patterns = qw/1968 010110101010170130 1969 010101101010000217 1970 100101101101000206 1971 010010101110150127/;

if (substr ($Lunar_Year_Patterns{$Lunar_Year},13,1) =~ /A/) {
         $Leap_Month = 10;
} elsif (substr ($Lunar_Year_Patterns{$Lunar_Year},13,1)=~ /B/){
        $Leap_Month = 11;
} elsif (substr ($Lunar_Year_Patterns{$Lunar_Year},13,1)=~ /C/){
        $Leap_Month = 12;
} else {
$Leap_Month = substr($Lunar_Year_Patterns{$Lunar_Year},13,1);
}

my $First_Lunar_Day_In_Gregorian_Month = substr($Lunar_Year_Patterns{$Lunar_Year},14,2);
my $First_Lunar_Day_In_Gregorian_Day = substr($Lunar_Year_Patterns{$Lunar_Year},16,2);

my $AddMonth;
if ( (($Leap_Month ==1) && ($Lunar_Month == $Leap_Month) && ($Leap_Month > 0)) || (($Lunar_Month > $Leap_Month) && ($Leap_Month>0) ) ){
    $AddMonth = $Lunar_Month +1;
} else {
$AddMonth = $Lunar_Month;
}

my $AddDay;
$AddDay = $Lunar_Day;

for(my $i = 1; $i <= $AddMonth - 1; $i++){
$AddDay = $AddDay +29 + substr($Lunar_Year_Patterns{$Lunar_Year},$i,1);
}


my @Gregorian = Add_Delta_Days($Lunar_Year,$First_Lunar_Day_In_Gregorian_Month,$First_Lunar_Day_In_Gregorian_Day,$AddDay -1);
print @Gregorian;

Ответы [ 2 ]

10 голосов
/ 17 декабря 2009

DateTime - 800-фунтовая горилла обработки даты. Он довольно большой, но он большой, потому что он много делает, и, что более важно, он делает это правильно .

С DateTime вы просто создадите объект DateTime для начальной даты, а затем получите конечную дату, добавив: $dt->add(days => $add_days).

Кроме того, есть DateTime :: Calendar :: Chinese , с которым вы можете сравнить свои результаты, даже если вы хотите заново изобрести это колесо:)

4 голосов
/ 17 декабря 2009

Проверьте дельта-функции в Date :: Calc и Date :: Calc :: Object и Date :: Calc :: PP . В частности, вы можете посмотреть на подпрограмму DateCalc_add_delta_days в источнике PP .

Вы также можете попробовать поискать источник Календарь :: Китай .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...