我正在尝试使用Perl将中国月球系统转换为格里高利,无论是出于娱乐还是出于学习目的。我认为有一些简单的数学算法来完成这项工作,但事实证明我错了。无论如何,经过一番谷歌搜索后,我找到了一些可以完成这项工作的SAS代码。好吧,对我来说,弄清楚如何重写Perl中的大部分代码并不困难。但是有这样的事情:
Convert2Gregorian = INTNX ('day', conDate, AddDay-1);
谷歌告诉我,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;
答案 0 :(得分:10)
DateTime是800磅重的日期处理大猩猩。它非常大,但它很大,因为它做了很多,更重要的是,它做到了正确。
使用DateTime,您只需构建开始日期的DateTime
对象,然后通过添加:$dt->add(days => $add_days)
获取结束日期。
此外,还有一个DateTime::Calendar::Chinese你可以比较你的结果,即使你想重新发明这个特殊的轮子以获得乐趣:)
答案 1 :(得分:4)
查看Date::Calc和Date::Calc::Object以及Date::Calc::PP中的增量功能。具体来说,您可能希望查看PP source中的DateCalc_add_delta_days
子例程。
你也可以尝试查看Calendar::China的来源。