I'm trying to convert Chinese lunar system to Gregorian using Perl, both for fun and for learning purposes. I thought there was some kind of easy mathematical algorithm to do the job but turned out I was wrong. Anyway, after a little googling around I came aross some ready SAS code that could do the job. Well, it was not too difficult for me to figure out how to rewrite most of the code in Perl. But there is something like this:
Convert2Gregorian = INTNX ('day', conDate, AddDay-1);
Google tells me that INTNX is a function that can return a date after which a certain date interval has been added. But using the keywords "Perl INTNX" gave me nothing useful. I then found a script written in Javascript, the general approach is about the same except that the Javascript uses Dateadd function, something like:
Return DateAdd(DateInterval.Day, AddDay - 1, conDate)
I also tried searching using PPM but was unable to find the module I wanted. Can someone kindly give me some pointers?
Thanks in advance :)
Update
Thanks to @psilva and @hobbs :)
Haha, finally I can translate one programming language to another. It's fun :) Just for fun and maybe for later reference: Here's the original SAS code and the Perl code translated by me. Correct me if I'm wrong :)
Note: Data incomplete.
SAS CODE IS AS FOLLOWS:
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;
TRANSLATED Perl CODE IS AS FOLLOWS: didn't handle the undefined situations for the moment
(I Changed the original SAS variable names)
#!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;