2009-12-17 83 views
2

我試圖將中國月球系統轉換爲使用Perl的Gregorian,既有趣又有學習的目的。我認爲有一種簡單的數學算法來完成這項工作,但事實證明我錯了。無論如何,經過一段時間的搜索後,我發現一些SAS代碼可以完成這項工作。那麼,我就不難想出如何重寫Perl中的大部分代碼。但也有一些是這樣的:是否有一個Perl的等效的SAS'INTNX函數或JavaScript的Dateadd函數?

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; 

TRANSLATED的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; 

回答

10

DateTime是日期處理的800磅重的大猩猩。這是相當大的,但它很大,因爲它做了很多,更重要的是,它做到了right

使用DateTime,您只需爲起始日期構造DateTime對象,然後通過添加以下內容獲取結束日期:$dt->add(days => $add_days)

此外,還有一個DateTime::Calendar::Chinese,您可以用比較你的結果,即使你想徹底改造這個特殊的輪子的樂趣:)

+0

@hobbs,謝謝你的指針。我會嘗試DateTime。謝謝:) – Mike 2009-12-17 11:47:28

+2

DateTime的+1。這是我在處理其他語言時最想念的Perl「特性」之一。 – 2009-12-17 12:46:21

4

查看Date::CalcDate::Calc::ObjectDate::Calc::PP中的三角函數。具體而言,您可能需要查看PP source中的DateCalc_add_delta_days子例程。

您也可以嘗試查看Calendar::China的來源。

+0

@psilva,感謝指針。 Data :: Calc中的add_delta_days似乎是我一直在尋找的東西。我正在嘗試。 – Mike 2009-12-17 11:44:19

+0

避免鏈接到特定於版本的文檔。鏈接很容易變得陳舊。 – daxim 2009-12-17 13:08:40

+0

@daxim:你如何鏈接到非版本特定的源代碼? – 2009-12-17 18:17:37

相關問題